JavaScript has eight different data types: String, Number, Boolean, Null, Undefined, Symbol, BigInt, and Object. These data types are categorized into two major kinds: primitive and reference data types.
In a JavaScript engine, primitive and reference data types are stored in different memory spaces. Primitive data types are stored in the stack memory, and reference data types are stored in the heap memory.
Before we take a practical look at how primitive and reference data types are stored and accessed in memory, let's have a high-level understanding of these concepts first.
Primitive data types
- String, Number, Boolean, Null, Undefined, Symbol, and BigInt are primitive data types.
- Primitive data types have fixed sizes, so the runtime can allocate a fixed amount of memory and store them in the stack.
Reference data types
- Objects, arrays, dates, etc., are reference data types in JavaScript.
- Unlike primitive data types, reference data types don't have fixed sizes. So, the runtime can't allocate a fixed memory and store them in the heap.
Enough theory. Let's take a practical look now.
Take a look at the left side of the above diagram. Let's do it together and create a variable name
. Since the value of the name
variable is of type String
, it's a primitive data type. So, it is stored in the stack memory as name = 'Mike'
.
In the next line, let's create another variable newName
and assign the name
variable to it. This new variable is also a primitive data type, so it is stored as newName = 'Mike'
in the stack.
Moving to the third line, let's change name = 'Michael'
. This updates the stack as name = 'Michael'
. Notice that this doesn't change the value of newName
, and its value is still 'Mike' in the stack.
This is because the JavaScript engine created a copy of the name
variable and assigned it as the value of newName
. Later, though we changed the value of the name
variable, it didn't affect newName
because newName
holds a copy of the original name
variable. This behavior is specific to primitive data types.
Next, let's create a person
object. Since an object is a reference data type, it is stored in the heap memory, and a reference person
is created to the object from the stack memory.
In the next line, let's create a new variable newPerson
and assign the person
object as its value. Being an object a reference type, the newPerson
variable references the same person
object in the heap from the stack.
Moving to the next line, let's update the name property of the person
object. Doing so changes the value of both person.name
and newPerson.name
and makes them the same. This is because the newPerson
object references the original person
object in the heap. So, changing a property in either object will change it in both objects. This behavior is specific to reference data types.
See the difference between primitive and reference data types? In short, when a primitive data type is assigned as the value of another variable, it creates a copy of the assigned variable. However, when a reference data type is assigned as the value of another variable, it doesn't create a copy; rather, it references the same object in the heap.
That's it. I hope this gives you some ideas of what primitive and reference data types are and how they work in JavaScript.