Primitive Values And Reference Values As Regards Memory Allocation
Understanding how JavaScript handles primitive and reference value
Table of contents
All programming languages have their in-built data structures, however, they differ from each other.
In this article, we would understand the types in JavaScript and learn the different types with references to their use cases and memory allocation. Javascript is a loosely-typed programming language as it allows to assign and reassign values of different types to a variable.
In JavaScript, we have 8 data types which are
- String
- Number
- Boolean
- Null
- Undefined
- Functions
- Array
- Objects.
The values of these types are classified into Primitive Values and Non-primitive/Reference Values. The primitive values are values of the data types that includes String, Number, Boolean, Null, and Undefined while the Non-primitive or reference values are values of the data types Functions, Array, and Object.
Therefore Primitive Data Types are data types of the primitive values and Non-primitive/Reference Data Types are data types of the reference values. When you declare a variable, the JavaScript engine allocates the memory for them on two memory locations which are the STACK and HEAP.
I wrote an in-depth article about the JavaScript runtime engine here. You can check it out to understand how the JavaScript environment handles variable allocation.
Primitive Data Type
Primitive data types are immutable i.e they can not be modified.
A primitive data type is a sub-class that allows the assignment of a variable to be by value. When a variable is assigned to a value with the primitive data type, the Javascript engine allocates the memory for it on a stack.
A stack is a data structure that allows elements to be added and removed in a particular order. It can be used to store static data. A static data means that the Javascript engine knows the size of such data at compile time.
Let us check out this example to understand better.
let foo = 20 // Initial assignment
let bar = foo // Assignment of variable *bar* to *foo* variable
foo = 40 // Re-assignment
console.log(foo) // 40
console.log(bar) // 20
From this code, we can see that the variable foo
was initially assigned the value of 20 and that variable is pushed to the top of the stack. A new variable bar
was assigned to foo
, in the case of a primitive data type of which the type number
is inclusive, only the value of foo
which is 20 is assigned to bar
. The variable bar
with its value is pushed to the call stack.
In the next line, we can see a reassignment of the value 40 to the variable foo
. When we log both variables to the console, we can see the results of both variables.
From the code above, we can understand that the reassignment of a value to a primitive data type does not change the value of the initial assignment.
From the image above, we can see that for each assignment of the variables, they are placed at the top of the stack.
Reference Data Type
Reference data types are mutable i.e they can be easily modified.
In reference type, the assignment of a variable is done by reference. All the reference data types are technically objects so we would collectively refer to them as Objects.
The variables that are assigned to a non-primitive value are usually given a reference to that value. This reference points to that object's address/location in memory. Note that the variables do not themselves contain the value.
let obj = { a: 'I', b: 'love', c: 'JavaScript'}
let newObj = obj
newObj.c = 'Python'
console.log (obj) // { a: 'I', b: 'love', c: 'Python' }
console.log(newObj) // { a: 'I', b: 'love', c: 'Python' }
In the code above, we created an object in memory, and a location and an address of the array are created. Using memory allocation, the address is the stack while the location is the heap. All variables usually first point to the stack. If it is a non-primitive value, the stack would contain a reference to the object in the heap.
From the image above, we can see that for the assignment of the obj
variable, the value is not associated with the variable rather an address/reference is pushed to the stack, and a location/object is pushed to the heap. For the assignment of the newObj
variable to the obj
, it points to the same address and location of the obj
variable. When there is a reassignment of the new Obj
property, this affects the location thereby changing the value of every variable that points to that location, in our case, affecting the obj
and newObj
variables.
The memory of the heap is not usually ordered which is why we need to keep a reference to it in the stack.
We can think of the REFERENCES in the stack as the ADDRESS and the OBJECTS in the heap as the LOCATION that the address belongs to.
CONCLUSION
In this article, we were able to:
Understand the various JavaScript data types which are String, Number, Boolean, Null, Undefined, Functions, Array, and Objects.
Understand that primitive data types are immutable i.e they can not be modified, and a non-primitive data type can be easily modified.
Understand how JavaScript handles primitive values and non-primitive values using HEAP and STACK.
RESOURCES
Some resources that helped me understand this concept better include:
If you found this article helpful, don't forget to give a thumbs-up π , and please share with your network. I would appreciate a comment if you have any questions or feedback.
Happy codingππ!!!