Memory Model
MedJavaScript 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;56// Objects (stored in Heap)7let obj1 = { x: 1 };8let obj2 = obj1;9obj2.x = 99;1011console.log(a, obj1.x);
Stack
(empty)
Heap
(empty)
Script starts. Stack is empty.
1 / 8
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