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.
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.
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.