By Rahul — Google Frontend Engineer
The Basics
JavaScript automatically manages memory. When you create objects, arrays, or strings, memory is allocated. When they are no longer reachable, the garbage collector frees the memory. You do not call free() like in C — but you can still cause memory leaks.
Reachability
The GC starts from "roots" (global object, currently executing function's variables, closures) and marks everything reachable from them. Anything not reachable is garbage.
Mark-and-Sweep (Modern V8)
- Mark phase: Starting from roots, mark all reachable objects
- Sweep phase: Free memory of all unmarked objects
- Compact: Move remaining objects together to reduce fragmentation
Generational Collection in V8
V8 divides memory into two areas:
- Young Generation (1-8MB): Newly created objects. Collected frequently with a fast "Scavenger". Most objects die young
- Old Generation (up to GBs): Objects that survived multiple young-gen collections. Collected less frequently with Mark-Sweep-Compact
Common Memory Leak Patterns
Forgotten Timers
Detached DOM Nodes
Closures Holding Large Data
WeakRef and FinalizationRegistry
Debugging Memory Leaks
- Chrome DevTools → Memory tab → Take Heap Snapshot
- Compare snapshots before and after a suspected leak
- Look for growing "Detached DOM trees" and increasing object counts
- Use
performance.measureUserAgentSpecificMemory()for production monitoring
Summary
V8 uses generational mark-and-sweep garbage collection. Most objects die young. Memory leaks happen from forgotten timers, detached DOM nodes, and unbounded caches. Use Chrome DevTools Memory tab to find leaks. Use WeakMap/WeakSet for caches that should not prevent GC.