The "Returning a Function" section describes an example with a nested function.
I actually don't understand how
counter remembers the
currentCount variable every time it is run, given what was written in the same section that the
LexicalEnviroment is erased from memory every time the function ends, and it is recreated every time it is started.
I don't understand where
currentCount is stored if the lexical environment is erased every time?
Questions like these bring tears to my eyes.
It's simple –
LexicalEnvironment is indeed destroyed after the call ends.
But in the example, the work is not finished, because the returned function retained a reference to the parent [
makeCounter ] variable object.
That is, while the returned function is alive, the parent LE must be preserved, what if, when executing, you need to turn to the parent function for variables (which happens: there is no
currentCount variable in the returned function)?
Garbage collectors work according to the reference algorithm (Mark and sweep), in general it is something like this:
- Roots are found, that is, something that will always exist (in browsers, this is the
windowobject, but it cannot be deleted).
- After each awakening, he [the collector] recursively walks the roots and marks everything he can reach; it is considered necessary and useful. Everything else is considered unattainable and the memory from under them is returned to the environment.
Now remember that the returned function, conditionally stored in
window , refers to the parent
LexicalEnvironment via the
[[Scope]] hidden property.
The collector simply cannot remove it –
window -> counter -> [[Scope]] .
This explains why the new
makeCounter call created a pristine counter – each function call gives it a crystal new
Closures are a very interesting thing in general, which can be very powerful, and can be completely confusing if you don't know how closures work.