No history yet

Memory Models and Values

Where Data Lives

When you declare a variable in JavaScript, the engine needs to find a place in your computer's memory to store its value. It doesn't just toss data anywhere. Instead, it uses two distinct regions of memory, each with its own rules and purpose: the stack and the heap.

The stack is for static memory allocation, while the heap is for dynamic memory allocation. This distinction is the key to understanding how JavaScript handles different types of data.

Think of the stack as a neat, orderly pile of boxes, each with a fixed size. It's used for storing primitive data types: string, number, boolean, null, undefined, symbol, and BigInt. When a function is called, a new block of memory (a "stack frame") is created on top of the stack to hold its local variables. Because the size of each primitive value is known ahead of time, the engine can manage this memory very quickly. When the function finishes, its frame is popped off the top of the stack, and the memory is instantly available again. This Last-In, First-Out (LIFO) process is extremely efficient.

let score = 100; // Stored on the stack
let name = "Alice"; // Stored on the stack
let isActive = true; // Stored on the stack

The heap, on the other hand, is a much less organized space. It's like a large, open warehouse where the engine stores objects and arrays, which can grow and shrink in size unpredictably. Because their size is dynamic, they can't be stored on the stack. Instead, the actual object is placed on the heap, and a pointer to its location is stored in a variable on the stack. This pointer is simply the object's —its unique identifier in the vast space of the heap.

Value vs. Reference

This difference in storage leads to a fundamental concept in JavaScript: how values are copied.

Primitives are copied by value. When you assign one variable to another, the actual value is duplicated. The two variables are completely independent.

let a = 50;
let b = a; // The value 50 is copied into b.

a = 99; // Changing 'a' has no effect on 'b'.

console.log(a); // 99
console.log(b); // 50

Objects and arrays, on the other hand, are copied by reference. When you assign one variable to another, you're only copying the memory address—the pointer. Both variables now point to the exact same object on the heap. If you modify the object using one variable, the change will be visible through the other.

let person = { name: "Carol" };
let anotherPerson = person; // Copies the reference, not the object.

anotherPerson.name = "David"; // Mutates the object on the heap.

console.log(person.name); // "David"

This is a common source of bugs for developers. Forgetting that two variables point to the same object can lead to unintended side effects, where changing one piece of data accidentally alters another.

Cleaning Up the Mess

Since the heap is for dynamic data, what happens when an object is no longer needed? In languages like C, the programmer is responsible for manually freeing up that memory. Forgetting to do so leads to "memory leaks," where unused memory is never returned to the system, eventually causing the application to crash.

JavaScript saves us from this hassle with a process called garbage collection. The JavaScript engine, such as Chrome's engine, periodically runs a garbage collector in the background. Its job is to find objects on the heap that are no longer reachable—meaning no variables on the stack (or other objects) still have a reference to them. Once identified, these orphaned objects are swept away, and their memory is freed.

This automatic process makes development much easier and safer, but it's not a free pass to ignore memory management. Understanding the fundamentals of the stack, the heap, and the difference between value and reference types is crucial for writing efficient, bug-free code and diagnosing complex problems.

Quiz Questions 1/5

In JavaScript, where are primitive data types such as number and boolean stored?

Quiz Questions 2/5

Consider the following code snippet. What will be logged to the console?

let person1 = { name: 'Alice' };
let person2 = person1;

person2.name = 'Bob';

console.log(person1.name);