Memory Heap & Garbage Collection
Where Your Objects Live and Die
LinkedIn Hook
You never call
malloc()orfree()in JavaScript. Memory just... happens. But that's a trap.Behind the scenes, the JS engine splits memory into two regions: the Stack (for primitives and function frames) and the Heap (for objects, arrays, and functions). A garbage collector walks the heap, marks everything still reachable from the roots, and sweeps away the rest. Anything unmarked — gone.
The problem? Your code can quietly keep objects "reachable" long after you stop needing them: a forgotten
setInterval, a removed DOM node still held by a variable, a global created by a missinglet. All four common leak patterns trap the garbage collector.In this lesson you'll learn the Mark-and-Sweep algorithm, the 4 classic leak patterns, and how ES2021's WeakRef lets you hold a reference that doesn't block GC.
If you've ever had a Node process quietly eat 2GB of RAM — this is the lesson that explains why.
Read the full lesson -> [link]
#JavaScript #InterviewPrep #GarbageCollection #MemoryLeak #JSEngine #Performance #WebDevelopment
What You'll Learn
- The difference between Stack and Heap memory in JavaScript
- How Mark-and-Sweep garbage collection actually works
- The 4 most common memory-leak patterns and how to fix each
- What
WeakRefandFinalizationRegistryare for
Two Regions of Memory
JavaScript manages memory automatically. You don't need to malloc() or free() like in C. But understanding how it works helps you avoid memory leaks.
Two Parts of Memory
| Area | What's Stored | Structure |
|---|---|---|
| Call Stack | Primitives (number, string, boolean, etc.), function calls, references | Ordered, LIFO |
| Memory Heap | Objects, arrays, functions (anything complex) | Unstructured, large pool |
Code Example — Stack vs Heap
// Primitives -> stored on the STACK
let a = 10;
let b = a; // b gets a COPY of a's value
b = 20;
console.log(a); // 10 (unchanged — separate copy)
// Objects -> stored on the HEAP
let obj1 = { name: "Rakibul" };
let obj2 = obj1; // obj2 gets a COPY of the REFERENCE (pointer)
obj2.name = "Hassan";
console.log(obj1.name); // "Hassan" (CHANGED — same object!)
Garbage Collection — Mark & Sweep Algorithm
JavaScript uses the Mark & Sweep algorithm:
- Mark Phase: Start from "roots" (global object, call stack variables). Follow all references and mark every reachable object.
- Sweep Phase: Go through ALL objects in the heap. Anything not marked gets deleted.
function createUser() {
let user = { name: "Rakibul", scores: [90, 85, 92] };
return user.name; // only the string is returned
}
let result = createUser();
// After createUser() returns:
// - `user` variable is gone (popped off stack)
// - The object { name: "Rakibul", scores: [...] } has NO references
// - Garbage collector will SWEEP it away
// - The returned string "Rakibul" is still alive (referenced by `result`)
Common Memory Leak Patterns
1. Accidental Global Variables
function leak() {
// Missing 'let/const' -> creates a global variable!
oops = "I'm stuck on window forever";
}
leak();
// window.oops exists -> never garbage collected
2. Forgotten Timers
// This creates a memory leak
const data = loadHugeData();
setInterval(() => {
// `data` is captured in this closure — can never be GC'd
// even if you no longer need it
process(data);
}, 1000);
// Fix: clear the interval when done
const timer = setInterval(() => process(data), 1000);
clearInterval(timer); // Now `data` can be GC'd
3. Detached DOM Nodes
let button = document.getElementById("myButton");
document.body.removeChild(button);
// The DOM node is removed from the page BUT
// `button` still holds a reference -> not garbage collected!
button = null; // Now it can be GC'd
4. Closures Holding Large Data
function outer() {
const hugeArray = new Array(1000000).fill("data");
return function inner() {
// inner() closes over `hugeArray` even if it never uses it
// in some engines (older V8), the entire closure scope is retained
console.log("Hello");
};
}
const fn = outer(); // hugeArray may stay in memory
WeakRef and FinalizationRegistry (ES2021)
// WeakRef: holds a reference that doesn't prevent garbage collection
let obj = { data: "important" };
let weakRef = new WeakRef(obj);
console.log(weakRef.deref()); // { data: "important" }
obj = null; // now the object CAN be garbage collected
// Later...
console.log(weakRef.deref()); // undefined (if GC has run)
Common Mistakes
- Forgetting to
clearInterval/clearTimeoutwhen a component unmounts — the closure keeps captured data alive forever. - Holding a JS reference to a DOM node after removing it from the page — the node is "detached" but not GC'd.
- Omitting
let/constinside a function and accidentally creating a global that never goes away. - Assuming
consthelps with memory — it only prevents re-binding; the object it points to is still on the heap and GC'd only when no references remain.
Interview Questions
Q: What's the difference between Stack and Heap memory in JavaScript?
The Stack stores primitives (numbers, strings, booleans, etc.) and function frames in a strict LIFO order. The Heap stores objects, arrays, and functions in an unstructured pool. When you assign an object to a variable, the stack holds a reference (pointer) into the heap.
Q: Where are primitives vs objects stored in memory?
Primitives live on the stack, objects/arrays/functions live on the heap. That's why
let b = awith primitives creates a copy, but with objects creates a shared reference.
Q: How does garbage collection work in JavaScript?
Using the Mark-and-Sweep algorithm. The GC starts from roots (global object, stack variables), marks every object reachable through references, then sweeps the heap and frees anything unmarked.
Q: Explain the Mark & Sweep algorithm.
Mark Phase: walk from the roots and flag every reachable object. Sweep Phase: traverse the heap and free any object that wasn't flagged. The flags are then cleared for the next cycle.
Q: Name 3 common causes of memory leaks in JavaScript.
- Accidental globals — forgetting
let/constcreates variables onwindowthat persist forever.- Forgotten timers/callbacks —
setIntervalor event listeners that capture large data in closures and are never cleared.- Detached DOM references — removing a DOM node from the page but keeping a JS variable pointing to it.
Q: What is a WeakRef and when would you use it?
WeakRefcreates a reference to an object that doesn't prevent garbage collection. Useful for caches where you want the data available if it exists but don't want to force it to stay in memory. Call.deref()to access the value — it returnsundefinedif the object was collected.
Quick Reference — Cheat Sheet
MEMORY MODEL — QUICK MAP
STACK HEAP
----- ----
primitives (number, str...) objects
function frames arrays
references (pointers) functions
LIFO, fast unstructured, larger
GARBAGE COLLECTION (Mark & Sweep)
1. Mark -> from roots, flag all reachable objects
2. Sweep -> free every unflagged object on heap
COMMON LEAKS
1. Accidental globals (missing let/const)
2. Forgotten setInterval / event listeners
3. Detached DOM nodes still held by JS vars
4. Closures retaining large data
WeakRef (ES2021): reference that does NOT block GC
FinalizationRegistry: run a callback when object is GC'd
Previous: var vs let vs const Next: Lexical Scope
This is Lesson 1.6 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.