Reachability decides survival
JavaScript memory is managed automatically. The collector keeps any object that is reachable from a set of roots, such as the global object and the current call stack, and frees the rest. You never call free yourself.
- The mark phase follows references from the roots.
- Anything reached is considered live.
- Everything else is swept and reclaimed.
Generational and incremental work
Modern engines use a generational model because most objects die young. New objects live in a small nursery that is collected often, and survivors get promoted to an older space collected less frequently.
- Collection runs incrementally to avoid long pauses.
- Reference cycles are still collected since reachability, not counting, decides liveness.
- The work competes with your code for the main thread.
A memory leak in this model is not unfreed memory but an object that stays reachable by accident, often through a lingering listener, a closure, or a global cache. Cut the reference and the collector does the rest.
Key idea
The collector frees whatever is unreachable from roots, so leaks come from references you forgot to drop, not from missing manual frees.