Primitive vs Reference Values in JavaScript

If you are familiar with JavaScript, You might know that JavaScript has these data types - Boolean, Null, Undefined, Number, BigInt, String, Symbol, and object. While this is true, JavaScript has mainly two types of values:

  • Primitive values

  • Reference values

We will look at What are Primitive and Reference values, how are they stored in the memory and how are they different from each other.

Primitive Values

In JavaScript, Primitive values are values that are not objects, and therefore have no methods and properties on them. Primitive data types include string, number, bigInt, boolean, undefined, null, symbol.

Primitive values are mostly represented at the lowest level of the language implementation. All primitive values are immutable. they cannot be altered in the ways an object or an array can be altered.

I have mentioned above, that primitive values are objects and thus, do not have methods or properties. But we surely access methods on a string. for eg, "something".indexOf("me"). How does this happen? So, when we try to access properties on primitives, JavaScript auto-boxes the value into an Object wrapper and then accesses the property on that object instead. For the above example, "something".indexOf("me") creates a String wrapper object and calls String.prototype.indexOf() on that object.

Reference Values

Reference values are mostly objects, and thus have access to methods and properties. It includes arrays, functions, collections, and all other types of objects.

Unlike primitive data types, reference values are dynamic in nature and do not have a fixed size.

The difference between the Primitive and the Reference values

The two categories represent the two different ways they are stored in the memory.

The primitives are stored in the stack memory (the short-term memory) and are stored by the value, whereas Reference values are stored in the Heap (the long-term memory) and are stored by the reference. Let's understand what this means with some examples -

This is how primitives are stored -

let a = 10;
let b = a;
console.log(a === b); //true

a = 20;
console.log(a); //20
console.log(b); //10
console.log(a === b); // false

In the above example, we declared a variable a with a value of 10. then, we declared another variable b and set it equal to a. We changed the value of a to 20. but the value of b is still 10. This is because, primitives are stored by the value and what the variable b is storing is not the variable a itself but the value of the variable.

image.png

This is how Reference values are stored -

const one = {
    age : 10
}
const two = one;
console.log(one === two); //true;

one.age = 20;
console.log(one.age); //20
console.log(two.age); //20
console.log(one === two); //true;

Similar to what we did in the previous example, we created a constant object one and inside it, created an age property with a value of 10. We declared another constant two and set it equal to one. After this, we changed the value of the age property inside object one to 20. But this time, the value of the age property inside object two has also changed.

This is because the objects are stored by the reference. So, in the above example, the constant one is referencing the address of the object { age: 10 }, and the constant two is referencing the address of constant one which is pointing to the address of { age: 10 }.

Therefore, changing the value of the age property of object one, changes the property value inside the object two as well, since they are pointing at the same address.

image.png

Also, what do you thing the result here would be?

console.log({ age: 10 } === { age: 10 });

The answer is false! Why?

Because, even though the objects are the exact same and they have the exact same data, they are referencing different addresses. Therefore, we are not comparing the values here but the addresses.

And If you haven't noticed, we are able to change the value inside the object, even though it is a constant. Because of the same reason stated above, we can change the data inside the object because it will still point to the same address. But the constant cannot reference a new object.

conclusion

  • The primitive values are stored by the value and the reference values are stored by the reference.

  • When you store a primitive value (even if it's just a variable set to a value), you're storing a value itself into a new address.

  • Creating a copy of a variable with a primitive value will create a value copy and store it separately. Therefore, changing one variable's value won't affect the other.

  • A reference is created when a reference is copied from one variable to another, allowing two variables to refer to the same object. Therefore, changing one object via the variable will affect the other.