Garbage Collection
In short: JavaScript's garbage collector reclaims memory for anything that is no longer reachable — not tied, by any chain of references, back to a root like a global variable or a currently-running function's local variables. Reachable, however many steps away, means kept; unreachable means eligible for collection. You can never observe or force the exact moment collection happens — only reachability is something your code actually controls.

Reachable through a chain, however long
An object stays alive as long as something reachable points to it — directly, or through other objects:
Setting session to null doesn't make { name: "Asha" } unreachable —
savedUser still points straight at it. An object needs every path to
it cut before it becomes eligible for collection, not just one.
WeakMap: a reference that doesn't count
Sometimes you want to attach data to an object without that attachment
itself keeping the object alive forever. That's what WeakMap is for —
verified here only by what you can observe (the entry exists while the
key does), never by timing:
A regular Map would hold a strong reference to obj as a key —
the Map itself would keep obj reachable forever, even if nothing
else in the program still needed it. WeakMap holds its keys
weakly: that reference doesn't count toward reachability. Once every
other reference to obj is gone, it becomes eligible for collection —
and its entry in the WeakMap disappears along with it. Exactly when
that happens is decided by the engine; nothing here claims a specific
moment, because that part genuinely isn't observable from code.
Quick practice
What makes an object eligible for garbage collection?
In the session/savedUser example, why does savedUser.name still work after session = null?
Why does a WeakMap's key not keep its corresponding object alive forever?
