Code of the Day
AdvancedPerformance & Internals

Memory and garbage collection

How JavaScript reclaims memory automatically — and how to avoid leaks anyway.

JavaScript / TSAdvanced8 min read
Recommended first
By the end of this lesson you will be able to:
  • 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 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 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 setInterval you 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.

Finished reading? Mark it complete to track your progress.

On this page