Memory Leak Sources

Four classic causes of a JavaScript memory leak — forgotten listeners, uncleared timers, long-lived closures, and detached DOM nodes still referenced.

Purpose

A memory leak happens when something keeps a reference to data alive longer than intended, so the garbage collector — which only frees unreachable memory — can never reclaim it. Four sources account for most JavaScript memory leaks in practice.

The four sources

  • Forgotten event listener: addEventListener with no matching removeEventListener keeps whatever the listener’s closure captured alive indefinitely, even after the element or feature it was meant for is gone.
  • Uncleared timer: setInterval (or a chain of setTimeout calls) that’s never cleared keeps its closure — and everything it captured — alive for as long as the timer keeps running, often forever.
  • Long-lived closure: a closure attached to something that outlives its intended purpose (recall Execution Model, Scope, and Closures) — the general case the first two are specific instances of.
  • Detached DOM: a removed element that’s no longer in the page, but still referenced from JavaScript (a cached lookup variable, a closure) — the element, and everything it in turn references, stays in memory.

Behavior notes

  • A memory-snapshot comparison — one taken, some action repeated several times, another taken — is the standard way to confirm a suspected leak: a specific object count or “detached node” count that keeps growing across identical repeated actions, rather than stabilizing, indicates something is holding a reference it shouldn’t.
  • WeakMap/WeakSet (recall Map, Set, WeakMap, and WeakSet) exist specifically to attach data to an object without preventing its collection — a direct fix for some detached-reference patterns.

Common mistakes

  • Adding an event listener in a component’s setup without a matching removal in its teardown.
  • Caching a DOM element reference outside the scope that manages its lifecycle, outliving the element’s actual presence on the page.

Runtime notes

Garbage collection behavior is engine-specific in its details, but reachability — the principle these leaks all violate — is defined by ECMAScript and conceptually identical everywhere.

Taught in these lessons

Related reference

Updated 2026-09-03