Closures keep things alive
A closure is not a snapshot of a variable. It is a live handle on the scope that variable lives in, and that scope cannot be collected while you hold it.
When a function is created it keeps a pointer to the scope it was created in. Not copies of the variables: the scope itself. That is why a closure created before a variable changes still sees the new value, and why the classic loop-with-var bug prints the final index three times: there was only ever one binding.
The memory consequence is the part people miss. If a long-lived callback closes over a scope that also contains a large array, the array cannot be collected, even if the callback never touches it. Engines are getting better at pruning unreferenced captures, but the behaviour is not something to rely on. Keep the closure small, or pull out the one field you need before creating it.
The upside of the same mechanism is the module pattern, which is most of how JavaScript did encapsulation for twenty years and is still the cleanest way to build a counter, a memoiser, or the store you will write at the end of this phase. Private state is just a variable nobody else has a reference to.
You should now be able to
- Explain why a closure sees later changes to a captured variable
- Identify a closure that is retaining more memory than it needs
Loading…