Before delving into memory allocation in JavaScript, it's important to have a solid understanding of the differences between primitive and non-primitive data types. The following table summarizes these differences clearly:
Aspect | Primitive | Non-Primitive (Reference Types) |
Definition | Data types that are immutable (cannot be changed) and hold a single value. | Data types that are mutable (can be changed) and hold a reference to a memory location. |
Examples | number , string , boolean , null , undefined , symbol , bigint | object , array , function , date , etc. |
Storage | Stored directly in the stack memory. | Stored in heap memory, with a reference in the stack. |
Mutability | Immutable (their values cannot be changed). | Mutable (their values or properties can be modified). |
Memory Allocation | Each variable holds its own copy of the value. | Variables hold references (pointers) to the object in memory. |
Pass By | Pass-by-value: A copy of the value is passed when assigned or passed as function argument. | Pass-by-reference: A reference to the object is passed, so changes affect the original object. |
Methods | Do not have methods associated with them. | Can have properties and methods (e.g., arrays and objects have functions like push() , toString() , etc.). |
Example of Assignment | let a = 5; let b = a; Both a and b are 5. | let obj1 = { name: "John" }; let obj2 = obj1; Both obj1 and obj2 point to the same object. |
Default Value | undefined (for uninitialized variables). | null is often used as a placeholder for uninitialized or empty objects. |
Key Points:
Primitives are immutable, meaning their values cannot be changed directly.
Non-Primitives (objects, arrays, etc.) are mutable and can be modified.
If you'd like to see a practical example or need further details, feel free to ask!
Memory Allocation
In JavaScript, memory is allocated into two main regions: Stack and Heap.
1. Stack Memory
Definition: A region of memory that stores primitive data types and references to objects (explained in heap memory section) stored in the heap.
Structure: Works on the LIFO (Last In, First Out) principle. Each function call gets its own stack frame.
Primitive Data Types
Primitive data types in JavaScript include Number
, String
, Boolean
, Undefined
, Null
, BigInt
, and Symbol
. These are stored directly in the stack because they have fixed sizes.
Example with Primitives:
let a = 10; // Stored directly in stack
let b = 30; // Stored directly in stack
let c = a; // `c` is assigned a copy of the value in `a`
a = 20; // Changing `a` does not affect `c`
console.log(a); // Output: 20
console.log(c); // Output: 10
Explanation
Variable Declarations (
let a = 10; let b = 30;
):a
andb
are primitive types (Number
in this case), so their values are stored directly in the stack.
Assignment (
let c = a;
):When you assign
a
toc
, the value ofa
is copied toc
.This means
c
gets its own memory location in the stack, independent ofa
.
Value Update (
a = 20;
):When you update
a
, it only affectsa
's memory location in the stack.c
remains unchanged because it holds a copy of the value ofa
from the time of the assignment.
Output (
console.log(a); console.log(c);
):a
has been updated to20
, soconsole.log(a)
outputs20
.c
still holds the original value10
(copied froma
), soconsole.log(c)
outputs10
.
2. Heap Memory
Definition: A region of memory used to store non-primitive data types like
Objects
,Arrays
,Functions
.Structure: Provides a large, dynamic memory space for complex data structures. Unlike the stack, the heap is not organized in a strict order.
Non-Primitive Data Types
Objects and arrays are stored in the heap, and only their references are stored in the stack.
Example with Objects:
let obj1 = {
id: 20,
name: "Hridoy"
}; // Stored in heap, reference in stack
let obj2 = obj1; // `obj2` gets the same reference as `obj1`
obj2.id = 35; // Modifies the same object in the heap
console.log(obj1.id); // Output: 35
console.log(obj2.id); // Output: 35
Explanation
Object Creation (
let obj1 = {...};
):The object
obj1
is a non-primitive type (an Object). Non-primitive values are stored in the heap memory.However, the reference to this object (its memory location) is stored in the stack as part of the variable
obj1
.
Assigning Reference (
let obj2 = obj1;
):When
obj2
is assignedobj1
, it does not create a new copy of the object. Instead,obj2
points to the same memory location in the heap where the object is stored.Both
obj1
andobj2
now refer to the same object in the heap.
Modifying the Object (
obj2.id
= 35;
):Since both
obj1
andobj2
refer to the same object in memory, modifying the object throughobj2
(i.e.,obj2.id
= 35
) also updates the value ofid
in the same object.This change will be reflected when one access the object through either
obj1
orobj2
.
Key Differences Between Stack and Heap
Feature | Stack | Heap |
Storage | Primitive data and references | Non-primitive data (objects, arrays) |
Access Speed | Fast | Relatively slower |
Structure | Linear (LIFO) | Randomly allocated |
Lifetime | Cleared automatically after function execution | Cleared by Garbage Collector |
Data Copying | Value copying | Reference copying |
Example Combining Stack and Heap
function example() {
let a = 5; // Primitive, stored in stack
let b = a; // `b` gets a copy of `a`
let objA = { val: 10 }; // Object, stored in heap
let objB = objA; // `objB` gets a reference to `objA`
b = 10; // Changes `b` but not `a`
objB.val = 20; // Changes `objA.val` because both point to the same object
console.log(a, b); // Output: 5, 10
console.log(objA.val); // Output: 20
}
example();
Breakdown:
a
andb
are primitives and stored in the stack.objA
andobjB
are references stored in the stack, pointing to the same object in the heap.Modifying
b
does not affecta
because they are independent values.Modifying
objB.val
also modifiesobjA.val
because both point to the same object in the heap.
Garbage Collection
JavaScript uses Garbage Collection (GC) to free up heap memory no longer referenced.
When an object in the heap has no references pointing to it, it is eligible for garbage collection.
Example:
let obj = { name: "Jane" };
obj = null; // The object becomes eligible for garbage collection
Why are Primitive Types Immutable and Reference Types Mutable?
Primitive Types (Immutable)
Immutability means that once a primitive value is created, it cannot be altered.
When one try to change a primitive value, a new value is created rather than modifying the original value.
Example:
let a = 10;
let b = 30;
let c = a;
c = 'Hello';
In this example, c
is initially assigned the value of a
(which is 10
). When you update c
to 'Hello'
, the value of c
is simply reassigned to a new value. The original value of a
remains unchanged, because primitive values (like numbers) are immutable in JavaScript.
Why is this immutable?
Primitive types (like numbers, strings, booleans, etc.) are immutable, meaning their values cannot be modified once they're created. When you assign a primitive type to a new variable (like
let c = a
), you're creating a copy of the value, not a reference to the original.In the code above,
c
is assigned the value ofa
(10
), but laterc
is reassigned to'Hello'
. The value ofa
remains unchanged because reassigningc
doesn't affecta
. This is the key characteristic of immutability in primitive types: the original value isn't changed by assigning it to a new variable or updating the new variable.
Non-Primitive (Reference) Types (Mutable)
Mutability means that the value of a non-primitive data type can be changed after it is created.
JavaScript reference types include
object
,array
, andfunction
.When one assign a reference type to another variable, both variables point to the same memory location. Modifying one variable affects the other because they refer to the same object in memory.
Example:
let obj1 = { name: 'John' }; let obj2 = obj1; obj2.name = 'Doe'; console.log(obj1.name); // 'Doe' (obj1 is changed because both obj1 and obj2 refer to the same object)
Here,
obj1
andobj2
refer to the same object, so modifyingobj2
also changesobj1
.
Thanks for reading the blogs…