Curriculum Series

What are primitive values and reference values in JavaScript?

What are primitive values and reference values in JavaScript?

What are primitive values and reference values in JavaScript?

JavaScript

Primitive & Reference

Whenever you create a variable in JavaScript, that variable can store one of two types of data, a primitive value or a reference value. If the value is a number, string, boolean, undefined, null, or symbol, it's a primitive value. If it's anything else (i.e. typeof object), it's a reference value.

JAVASCRIPT
1// Primitive Values
2number
3string
4boolean
5undefined
6null
7symbol
8
9// Reference Values, anything that is "typeof" "object"
10objects
11arrays
12functions
JAVASCRIPT
1const age = 28; // primitive
2const name = 'Abhishek'; // primitive
3const loading = false; // primitive
4const user = undefined; // primitive
5const response = null; // primitive
6const counter = Symbol('counter'); // primitive
7
8const user = { name: 'Abhishek' }; // reference
9const friends = ['Rohit', 'Mohit']; // reference
10const doThing = () => ({}); // reference

On the surface primitive values and reference values look the same, but under the hood they behave much differently. The key difference can be seen in how they store their value in memory. If you looked at the in-memory value of a primitive, you'd see the actual value itself (28, 'Abhishek', false, etc). If you looked at the in-memory value of a reference type, you'd see a memory address (or a "reference" to a spot in memory). In practice though, what difference does it make? Let's take a look at some examples.

JAVASCRIPT
1let surname = 'Jakhar';
2let displayName = surname;
3
4surname = 'Abhishek';
5
6console.log(surname); // 'Abhishek'
7console.log(displayName); // 'Jakhar'

First we create a variable called surname and assign the string Jakhar to it. Then we create a new variable called displayName and assign it to whatever the in-memory value of surname is, which happens to be Jakhar. From there we change the in-memory value of surname to be Abhishek. Now, when we log surname we get Abhishek and when we log displayName we get Jakhar. Though this example demonstrates that the in-memory value of a primitive is the value itself, there's nothing surprising or really interesting going on here.

Let's look at a similar example but instead of using a primitive value, let's use a reference value.

JAVASCRIPT
1let laddu = {
2 type: 'Dog',
3 name: 'Laddu',
4};
5
6let burfi = laddu;
7
8burfi.name = 'Burfi';
9
10console.log(laddu.name); // Burfi
11console.log(burfi.name); // Burfi

First we create a variable called laddu and assign it to an object which has two properties, type and name. Then we create a new variable called burfi and assign it to whatever the in-memory value of laddu is, which is the reference to the spot in memory where the laddu object is located. At this point, both laddu and burfi are referencing the same spot in memory. What that means is when we modify burfi.name, because burfi and laddu are referencing the same spot in memory, it's as if we also modified laddu.name. That's why when we log laddu.name and burfi.name we get the same value, Burfi.

Let's look at one more example to cement your understanding. What do you think happens when, using the identity operator (===), we compare two primitives that have the same value?

JAVASCRIPT
1const name = 'Abhishek';
2const friend = 'Abhihek';
3
4name === friend; // true

Here we see that because name and friend have the same value, Abhishek, when comparing them, we get true. This probably seems obvious but it's important to realize that the reason we get true is because, with the identity operator, primitives are compared by their value. Since both values equal Abhishek, comparing them evaluates to true.

Now, what about reference values?

JAVASCRIPT
1const laddu = {
2 type: 'Dog',
3 name: 'Laddu',
4};
5
6const burfi = {
7 type: 'Dog',
8 name: 'Burfi',
9};
10
11laddu === burfi; // false

Even though laddu and burfi have the same properties and values, when comparing them with the identity operator, we get false. The reason for that is because, unlike primitive values, reference values are compared by their reference, or their location in memory. Above, even though laddu and burfi have the same properties and values, they're occupying different locations in memory.

Both these examples demonstrate how primitive types are compared by their value while reference types are compared by their reference.

An interesting by-product of primitive values is that they're always immutable. This make sense if you think of primitives in terms of their in-memory value. We said earlier that "if you looked at the in-memory value of a primitive, you'd see the actual value itself". The reason primitive values are always immutable is because whenever you change a primitive value, what you're actually doing is replacing the in-memory value. Because you can only replace the value and never modify it, by definition, that makes it immutable.

Finished reading?

Mark this topic as solved to track your progress.