JavaScript · Question 70
What commonly causes memory leaks in browser JavaScript, and how would you investigate them?
Direct answer
JavaScript leaks usually happen when data that is no longer useful remains strongly reachable through listeners, timers, closures, caches, DOM references, or global structures; garbage collection cannot reclaim objects that are still reachable.
Garbage collection can handle unreachable cyclic structures, so “circular references always leak” is outdated as a general rule. The practical question is whether an unwanted object remains reachable from a live root.
- Event listeners — long-lived targets retaining handlers that close over component/state data.
- Timers/subscriptions — intervals, observers, sockets, or custom subscriptions that are never cancelled/unsubscribed.
- Detached DOM — nodes removed from the document but still referenced by JavaScript data structures or closures.
- Unbounded caches — Maps/arrays storing request or object data forever.
- Closures — a small callback can unintentionally retain a much larger lexical object graph.
Investigation usually involves reproducing growth, using browser memory tooling/heap snapshots, comparing retained objects over time, and following retaining paths to understand why an object is still reachable. Fix the ownership/cleanup rule rather than calling garbage collection manually.