Memory and garbage collection
How JavaScript reclaims memory automatically — and how to avoid leaks anyway.
- Explain reachability-based garbage collection
- Recognise the common causes of memory leaks
- Connect leaks back to references and closures
JavaScript manages memory for you: you never free anything. A garbage
collector automatically reclaims memory you're no longer using. That's a huge
convenience — but "no longer using" has a precise meaning, and getting it wrong
causes memory leaks even in a garbage-collected language.
Reachability
The collector's rule is reachability: an object is kept alive as long as it can still be reached, by following references from "roots" (global variables, the current call stack, and so on). When nothing references an object anymore, it becomes unreachable and is eligible to be collected.
This ties straight back to the values-and-binding lesson: objects are referenced by arrows. While any arrow can reach an object, it stays. Drop the last arrow, and it can be freed.
How leaks happen
A leak is memory that's no longer needed but is still reachable, so the collector can't reclaim it. The usual culprits:
- Forgotten references in long-lived objects — pushing into a global array (or cache) that's never cleared. Every entry stays reachable forever.
- Detached DOM nodes — removing an element from the page but keeping a reference to it in a variable, so it can't be freed.
- Listeners and timers — an event listener or
setIntervalyou never remove keeps its callback (and everything that callback closes over) alive. - Closures holding more than you think — a closure (the closures lesson) keeps its entire surrounding scope reachable; capture only what you need.
Finding and fixing them
The symptom is memory that climbs over time and never comes back down. Browser devtools' memory profiler lets you take heap snapshots and compare them to find what's accumulating. The fix is almost always the same: drop the reference — clear the cache entry, remove the listener, clear the interval, null out the detached node.
Automatic GC doesn't mean leak-proof. Long-running apps (SPAs, servers) are where leaks bite — small accumulations over hours add up. Always pair "add a listener / start a timer / cache a thing" with a plan to remove it.
Where to go next
With timing and memory understood, you can measure real performance. Next: performance profiling.