🧠

Memory Model

intermediate

JavaScript uses two memory regions: the Stack for primitives and function calls, and the Heap for objects and dynamic data. Understanding this helps you predict performance, avoid memory leaks, and understand how garbage collection works.

🎮Interactive Visualization

Code
1// Primitives (stored in Stack)
2let a = 10;
3let b = a;
4b = 20;
5
6// Objects (stored in Heap)
7let obj1 = { x: 1 };
8let obj2 = obj1;
9obj2.x = 99;
10
11console.log(a, obj1.x);
Stack
(empty)
Heap
(empty)
Step 1/8Script starts. Stack is empty.
Key Insight: Primitives are copied by VALUE (independent). Objects are copied by REFERENCE (shared)!

Key Points

  • Stack: stores primitives (numbers, booleans, strings) and function call frames
  • Heap: stores objects, arrays, and functions (dynamic allocation)
  • Variables hold references (pointers) to heap objects, not the objects themselves
  • Garbage Collection: V8 uses mark-and-sweep to free unreachable objects
  • Memory leaks occur when objects remain referenced but are no longer needed

💻Code Examples

Primitives vs Objects

// Primitives stored in stack
let a = 10;
let b = a;    // Copy of value
b = 20;
console.log(a);  // 10 (unchanged)

// Objects stored in heap
let obj1 = { x: 1 };
let obj2 = obj1;  // Copy of reference
obj2.x = 99;
console.log(obj1.x);  // 99 (same object!)

Primitives are copied by value, objects by reference

Stack Frames

function outer() {
  let x = 1;  // Frame 1
  inner();
}

function inner() {
  let y = 2;  // Frame 2
  // Stack: [global, outer, inner]
}

outer();
// inner() returns → frame popped
// outer() returns → frame popped

Each function call creates a stack frame

Heap Allocation

// Each {} creates new heap object
function createUser(name) {
  return {
    name: name,
    data: new Array(1000)
  };
}

let user1 = createUser("Alice");
let user2 = createUser("Bob");
// Two separate objects on heap

Objects allocated on heap persist until GC

Garbage Collection

let obj = { data: "important" };

// obj is reachable → NOT collected

obj = null;

// Original object now unreachable
// GC will reclaim this memory
// in next collection cycle

Unreachable objects are garbage collected

Memory Leak

const cache = [];

function processData(data) {
  // BUG: cache grows forever!
  cache.push(data);
  return data.value * 2;
}

// Fix: limit cache size or use WeakMap
const weakCache = new WeakMap();

Unbounded caches cause memory leaks

Closures & Memory

function createCounter() {
  let count = 0;  // Kept alive by closure

  return () => ++count;
}

const counter = createCounter();
// 'count' lives in heap as long
// as 'counter' function exists

Closures keep variables alive on heap

Common Mistakes

  • Thinking primitives and objects are stored the same way
  • Forgetting that object assignment copies references, not values
  • Creating memory leaks with event listeners, closures, or global caches
  • Not understanding that garbage collection is non-deterministic

Interview Tips

  • Draw stack and heap diagrams for given code
  • Explain why === behaves differently for primitives vs objects
  • Know common memory leak patterns and how to fix them
  • Understand WeakMap/WeakSet for cache scenarios

🔗Related Concepts