Photo by Clément Hélardot on Unsplash
Understanding Primitive and Reference Data Types in JavaScript.
Primitive and Reference data types are the fundamental concepts when it comes to programming. The reason this is so important to understand is because when you are coding, if you do not have a strong understanding of primitive and reference types, you will run into tons and tons of bugs and related to this issue and you will be spending a lot of time debugging your code. This is also one of the favorite topics when it comes to interview questions and knowing this will definitely give you an edge.
So what are Primitive and Reference types?
In programming we often use variables. Variables are like placeholders that hold our data. This data can be of different types. They can be a Number, a string or a whole object. In JavaScript, data types are divided into 2 categories which are
Primitive types
Reference types
Primitive Types
Number, String, Boolean, Undefined and Symbols are primitive types. They are stored as simple data types. Whenever you assign a primitive type value to a variable the variable actually holds a copy of that value.
let numOne = 10
In the above snippet I have declared a variable numOne
and assigned it a Number 10. Number is a primitive data type so now numOne
has an actual copy of the value 10
let numOne = 10
let numTwo = numOne
console.log(numTwo)
Output
10
In the above snippet I have assigned numTwo
with numOne
which holds the value 10, so the numTwo
will have a copy of the data that numOne
is holding, The output of above snippet will print 10
on the console.
let numOne = 10
let numTwo = numOne
numTwo+=2
console.log(numTwo)
console.log(numOne)
Output
12
10
The above code snippet prints 12
and 10
because numTwo
is holding a copy of data that anumOne
has. This means any modifications I do on numTwo
will take effect on numTwo
's own copy of data and it wont affect variable numOne
in any way. This is why Primitive types are sometimes also called as value types because they deal with actual values.
Understanding what is happening under the hood.
When you create and initialize a variable with a primitive data type. The value of that variable gets stored on a stack. So when we created a variable numOne
and assigned it with a value of 10
what is happening behind the scenes is that your computer is pushing this variable numOne
with value 10
into the stack.
Next when we declare another variable numTwo
and assigned it with numOne
the computer copied the value of numOne
, assigned it to numTwo
and pushed numTwo
into the stack as well. That's how we ended up with two variables having their own copy of the same data.
When we modified the value of numTwo
by doing a numTwo + 2
The modification affected only numTwo
's copy of data in the stack and numOne
remained intact.
Reference Types
This is where things get interesting. These are complex data types which are stored as objects and have methods as well. Some examples of reference data types are Arrays, Objects, Dates, Functions, Collections.
What makes Reference types different
let objectOne = {
name:"Pratik",
age:23
}
In the above snippet I have created a variable objectOne
to store an object. But there is a catch, here the objectOne
does not store the object directly instead it stores an address of the object in the heap.
let objectOne = {
name:"Pratik",
age:23
}
let objectTwo = objectOne
I created a second variable objectTwo
to which I have assigned objectOne
Here is where the difference lies - unlike primitive types, when I do objectTwo = objectOne
, the value of objectOne
is again copied to objectTwo
like before but here the value of objectOne
is nothing but the address or the "reference" to the data stored in heap and not the actual data itself. This means that internally both the variables will now point to the same address in the memory and any modifications I do to either one of them will affect both of them.
let objectOne = {
name:"Pratik",
age:23
}
let objectTwo = objectOne
objectTwo.age = 29
console.log(objectTwo.age)
console.log(objectOne.age)
Output
29
29
Notice that I only changed objectTwo
's age value but objectOne
' age value also got changed. This is because when I modified objectTwo.age
, onjectOne.age
also got modified as they are both pointing to the same value in heap.
Understanding the science behind reference types
Unlike primitive types, which uses a single stack data structure to store data, reference types uses both stack and a heap. when we declare an object, the object itself or the value in the object is stored in the heap and the stack is used to store the reference or a pointer or address of that object. This means we can have multiple variables which can have the same address in the stack but all of those address will point to a single value in heap.
Wrapping Up
I hope you got some idea about Value and Reference types. These concepts are not just limited to JavaScript, they are used everywhere in programming and knowing them is very crucial and will save you a lot of time while debugging and also in interviews.