JavaScript Notes
Learn JavaScript garbage collection: mark-and-sweep algorithm, reference counting, memory lifecycle, memory leaks, WeakMap/WeakRef, and top interview Q&A.
What is Garbage Collection?
Garbage Collection (GC) is JavaScript's automatic memory management system. When you create objects, arrays, or functions, the engine allocates memory. When those values are no longer reachable (no variable points to them), the garbage collector automatically frees that memory.
One-liner: Garbage collection is JavaScript's automatic memory janitor — it removes values that are no longer reachable so memory doesn't fill up.
You don't call the garbage collector — it runs automatically in the background.
Memory Lifecycle Diagram
The Core Concept: Reachability
The garbage collector only cares about one question: Is this value reachable?
A value is reachable if it can be accessed from a GC root through any chain of references.
GC Roots (always reachable):
- Global variables
- Currently executing function's variables
- Variables in all functions on the call stack
- Variables referenced by closures
Mark-and-Sweep Algorithm
The modern GC algorithm used by JavaScript engines (like V8):
Basic Example — Object Becoming Unreachable
function createUser() {
const user = { name: "Amit", age: 28 }; // Memory allocated
return user; // Reference passed out
}
let profile = createUser(); // profile holds reference
console.log(profile.name);
profile = null; // Reference removed — object becomes unreachable
// GC can now free { name: "Amit", age: 28 }Amit
After profile = null, the object { name: "Amit", age: 28 } has no references. It becomes eligible for garbage collection.
Circular References
Circular references are handled correctly by mark-and-sweep (but not by old reference counting):
function createCycle() {
const a = {};
const b = {};
a.other = b; // a references b
b.other = a; // b references a — circular!
// a and b reference each other, but no external reference
}
createCycle();
// After function returns, both a and b are unreachable from GC roots
// Mark-and-sweep correctly identifies them as garbage(no output — both objects will be collected)
Memory Leaks — Common Causes
A memory leak happens when memory that should be freed stays reachable by accident:
Leak 1 — Accidental Global Variables
function processData() {
// WRONG — missing let/const/var → creates global variable!
data = { items: new Array(100000) };
}
processData();
// `data` is now a global — never garbage collected!// CORRECT
function processData() {
const data = { items: new Array(100000) };
// data is local — cleaned up after function returns
}Leak 2 — Forgotten Event Listeners
// CORRECT — remove listener when done
btn.removeEventListener("click", handler);
// OR use AbortController / { once: true }Leak 3 — Detached DOM Nodes
let detachedDiv;
function createLeak() {
const div = document.createElement("div");
document.body.appendChild(div);
detachedDiv = div; // Global reference keeps it alive
document.body.removeChild(div); // Removed from DOM
// But detachedDiv still holds reference → NOT garbage collected!
}// CORRECT — clear the reference when done
detachedDiv = null;Leak 4 — Closures Holding Large Data
function setupProcessor() {
const largeBuffer = new ArrayBuffer(10 * 1024 * 1024); // 10MB
return function process(input) {
// largeBuffer is captured in closure even if not used in process!
return input * 2;
};
}
const processor = setupProcessor();
// largeBuffer stays in memory as long as `processor` is aliveWeakMap and WeakRef — GC-Friendly References
JavaScript provides weak reference types that don't prevent garbage collection:
WeakMap
const cache = new WeakMap();
function process(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = obj.value * 2;
cache.set(obj, result); // Weak reference — doesn't prevent GC
return result;
}
let obj = { value: 21 };
console.log(process(obj));
obj = null; // Object becomes unreachable
// WeakMap entry is automatically removed — no memory leak42
WeakRef (ES2021)
let obj = { name: "Temporary" };
const weakRef = new WeakRef(obj);
console.log(weakRef.deref()?.name);
obj = null; // obj may be garbage collected
// weakRef.deref() may return undefined after GCTemporary
V8 Generational Garbage Collection
Modern JavaScript engines like V8 use generational GC for efficiency:
Common Mistakes
❌ Mistake 1 — Setting Variable to null to "Force" GC
let obj = { data: "..." };
obj = null; // Makes object eligible for GC — but doesn't FORCE itSetting to null makes the object eligible for GC — the actual collection happens when the engine decides (you can't force it directly in production code).
❌ Mistake 2 — Thinking Closures Always Cause Leaks
Closures are not automatically leaks. They only leak when:
- The closure is held in a long-lived reference (global, event handler)
- The closure captures a large or growing data structure
Short-lived closures are collected normally.
Interview Questions 🎯
Q1. What is garbage collection in JavaScript?
Garbage collection is JavaScript's automatic memory management mechanism. It automatically detects objects that are no longer reachable from any GC root and frees their memory. The developer doesn't need to manually allocate or free memory — the engine handles it.
Q2. What algorithm does modern JavaScript use for GC?
Modern engines (including V8, SpiderMonkey) use Mark-and-Sweep: starting from GC roots, the GC marks all reachable objects, then sweeps (frees) anything not marked. This correctly handles circular references, unlike the older reference counting approach.
Q3. What is the difference between mark-and-sweep and reference counting?
- Reference counting: Tracks how many references point to each object; frees when count = 0. Problem: cannot handle circular references (A→B→A, both counts never reach 0).
- Mark-and-sweep: Traces reachability from roots; frees anything not reachable. Advantage: handles circular references correctly.
Q4. What are common causes of memory leaks in JavaScript?
- Accidental globals — forgetting
let/const/var - Forgotten event listeners — listeners holding closures over large data
- Detached DOM nodes — removed from DOM but referenced by JS variable
- Closures capturing large data in long-lived functions
- Timers (
setInterval) not cleared when no longer needed
Q5. What is reachability in the context of GC?
An object is reachable if it can be accessed from a GC root (global scope, call stack, active closures) through any chain of references. Only reachable objects are kept in memory; unreachable ones are candidates for collection.
Q6. How do WeakMap and WeakSet help avoid memory leaks?
WeakMap and WeakSet hold weak references — they don't prevent their keys/values from being garbage collected. This makes them ideal for caches, metadata, and associations where you don't want to accidentally keep objects alive just because you added them to a map.
Q7. What is generational garbage collection?
A GC strategy where the heap is split into generations (young and old). New objects go to the young generation — which is collected frequently and quickly (most objects die young). Objects that survive multiple collections are promoted to the old generation, collected less often with a heavier algorithm. V8 uses this for efficiency.
Q8. Can you force garbage collection in JavaScript?
Not in production code. You can expose it in Node.js (--expose-gc flag + global.gc()), but this is for testing/profiling only. In normal applications, you influence GC by nulling references and keeping objects short-lived — the engine decides when to actually collect.
Key Takeaways 🔑
- JavaScript uses automatic garbage collection — you don't free memory manually
- The GC algorithm is Mark-and-Sweep: trace reachability from roots, sweep everything else
- A value is reachable if accessible from global scope, call stack, or active closures
- Circular references are NOT a problem for mark-and-sweep (only for old reference counting)
- Common memory leaks: accidental globals, forgotten listeners, detached DOM, large closure captures
WeakMap/WeakSet/WeakRefallow GC-friendly references- V8 uses generational GC — young/old generations for efficiency
- You cannot force GC — you can only make objects eligible by removing references
Summary
Garbage collection is JavaScript's automatic memory cleanup system. It tracks which objects are reachable from the program's roots (global scope, call stack, closures) using the Mark-and-Sweep algorithm, and frees anything that isn't. Understanding GC helps you write memory-efficient code: avoid accidental globals, clean up event listeners, null out references when done, and use WeakMap/WeakSet for caches. While you can't control the GC directly, knowing how it works helps you write code that gives it the best chance to work effectively.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Garbage Collection - Memory Lifecycle & Mark-and-Sweep Guide.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, advanced, garbage, collection
Related JavaScript Master Course Topics