I apologize in advance for yet another closure question, but I'd like to clarify my understanding of the way closures are implemented in JavaScript.
Consider the following code:
01 'use strict';
02 function foo() {}
03 foo();
I have established in a question earlier in the year that a closure is conceptually (if not actually due to engine optimizations) created here.
And until foo
is invoked on line 3 a corresponding execution context is not created.
So as far as I can tell from the spec, when evaluating this code:
- Each execution context has a "LexicalEnvironment" component used to resolve identifier references made by code within it (8.3, Table 23).
FunctionCreate
is called, passing in a reference (named "scope") to the "LexicalEnvironment" component of the current execution context. (14.1.19)FunctionCreate
callsFunctionInitialize
passing "scope" (9.2.5)FunctionInitialize
ensures that the [[Environment]] internal slot of the function-object being created is set to the value of "scope" (the reference to the "LexicalEnvironment" component of the current execution context) (9.2.4)
Finally, when foo
is actually invoked, I find the spec harder to interpret.
- In
PrepareForOrdinaryCall
, the "LexicalEnvironment" of the new execution context for the call is set to be the result of callingNewFunctionEnvironment
(9.2.1.1) NewFunctionEnvironment
copies the reference to the "LexicalEnvironment" component of the outer execution context (the [[Environment]] slot of the function-object) into theEnvironment
record (EnvironmentRecord
?) of the "LexicalEnvironment" component of the execution context under construction as the "outer lexical environment reference" (8.1.2.4)
Thus closures are implemented in a two step fashion:
- A linkage between function-object and the enclosing "LexicalEnvironment" of the enclosing execution context, is created at function-object instantiation time. This is the [[Environment]] internal slot of the function-object.
- When a function is invoked, this reference to the enclosing "LexicalEnvironment" component of the outer execution context (the contents of the [[Environment]] slot of the function object) is copied into a spec-imprecisely-defined(?)/
EnvironmentRecord
(?) sub-component of the "LexicalEnvironment" component of the new execution context.
Does this sound about right?