I\'m reading about JavaScript closures. I\'m familiar with Execution Contexts, how the Lexical Environment is maintained, and very familiar with Lexical Scoping.
I
According to the Wikipedia definition, as mentioned in the question, a closure is a
is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables) of that function.
The understanding of how execution contexts and lexical environments are maintained is known and the goal here is to understand when a function is returned, how is that referencing environment maintained/referenced?
Let's begin.
In section 8.6.2 on the ECMA 262 v 5 specification, it lists the internal properties of ECMAScript objects. The one to point out here is in table 9, the [[Scope]] property. According to the description of this property, it is described as
A lexical environment that defines the environment in which a Function object is executed. Of the standard built-in ECMAScript objects, only Function objects implement [[Scope]].
As we will see, the [[Scope]] property of a function object will always be set to the parent's lexical environment. We see this mentioned in section 13.2 which talks about the process of creating a function object. (Please note: function object in this context is referring to a native ECMAScript object, and not the accessible function object through code).
When a function is created, it sets the internal [[Scope]] property to the VariableEnvironment, LexicalEnvironment or Global Environment of the running execution context, depending on if the function is a function declaration, function expression or created through the Function constructor.
When control is given over to the global code, as well as when control enters function code, declaration binding instantiation occurs as part of initializing the execution context. Part of the declaration binding instantiation is to bind the function declarations within the scope of the current context by creating the function objects as mentioned in section 13.2. The below example shows this:
For example
// The global execution context has already been initialized at this stage.
// Declaration binding instantiation has occurred and the function
// foo is created as a new native object with a [[Scope]] property
// having the value of the global execution context's VariableEnvironment
function foo() {
// When foo is invoked, a new execution context will be created for
// this function scope. When declaration binding instantiation occurs,
// bar will be created as a new native object with a [[Scope]] property
// having the value of the foo execution context's VariableEnvironment
function bar() {
}
bar(); // Call bar
}
foo();
Another thing to look is the process that occurs upon entering/creating the execution context when entering a function. Below is a summary of what happens.
With the knowledge that a function maintains a reference to it's parent Lexical Environment through the internal [[Scope]] property, we can now see how closures work.
So to answer the question, a functions parent LexicalEnvironment is persisted through the internal [[Scope]] property of the function. Note that local variables within the function can be resolved when the function is run, only "free variables" need to be tracked and are done so by the [[Scope]] property.
Note: Please, if my information is incorrect, comment below.