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