The garbage collector (GC) frees every object that is no longer reachable from the roots: the global object, the call stack and handles held by the browser. A JavaScript memory leak is therefore an unwanted reference that keeps an object reachable.
V8 86,723 's collector, Orinoco, is generational because most objects die young. A fast Scavenger copies live objects between two semi-spaces of the small young generation; survivors of two scavenges move to the old generation, which a mark-sweep-compact collector processes less often, marking concurrently on helper threads.

The most common leak is a cache keyed by objects that outlive their use. A Map holds its keys strongly; a WeakMap (Map and WeakMap) lets the GC drop an entry once nothing else references its key. Node's --expose-gc flag exposes gc() so pending garbage does not blur the measurement:
const heapMB = () => { globalThis.gc(); return (process.memoryUsage().heapUsed / 1e6).toFixed(1); };
console.log('baseline', heapMB(), 'MB');
const strong = new Map(); // holds its keys strongly
for (let i = 0; i < 100_000; i++) strong.set({ id: i }, new Array(50).fill(i));
console.log('Map ', heapMB(), 'MB,', strong.size, 'entries');
strong.clear();
const weak = new WeakMap(); // holds its keys weakly
for (let i = 0; i < 100_000; i++) weak.set({ id: i }, new Array(50).fill(i));
console.log('WeakMap ', heapMB(), 'MB');baseline 3.8 MB Map 55.7 MB, 100000 entries WeakMap 4.0 MB
| Leak pattern | Kept alive by | Fix |
|---|---|---|
| Unbounded Map cache | The collection | WeakMap or LRU limit |
| Forgotten setInterval | Callback closure | clearInterval() |
| Listener on window | Listener closure | AbortSignal option |
| Detached DOM nodes | JS variables | Null the reference |
Finding a leak with heap snapshots
In Chrome 1 's Memory panel, take a Heap snapshot, repeat the suspect action (open and close a dialog) several times, and take another. View the second in Comparison mode: constructors whose count grows with the repetitions are the leak. Sort by Retained Size (memory freed if the object died, versus Shallow Size, the object alone) and read the Retainers pane to find the variable, listener or closure holding it. The filter Objects retained by detached nodes isolates removed elements still referenced from JavaScript; in Node.js 2,131 , v8.writeHeapSnapshot() writes a file the same panel loads. Avoid WeakRef and FinalizationRegistry (WeakRef) for cleanup: GC timing is unspecified.