I am following along with an article on javascript closures.
In trying to learn the particulars of execution context, I came across a result that surprised me.
var globalVar = 'g';
var inner;
var outer = function() {
var outerVar = 'o';
inner = function() {
var innerVar = 'i';
console.log(innerVar, outerVar, globalVar);
}
}
outer()
inner() // Q: What does this log out?
This actually outputs i o g
.
I expected to see i undefined g
.
Here is my understanding of the process. I would like to understand my error:
inner
is declared as a property on the global object and the value is set to undefined
outer
is invoked.outer
whose scope chain includes outerVar
and the global object.inner
property on the global object is assigned a reference to the function definition.outer
finishes. (the related scopes are removed? marked for GC?)inner
is invoked.innerVar
and the global object.outerVar
is not found in scopeCan someone please explain why outerVar
is defined?
When a function is created, it references its surrounding execution context as the scope, creating a closure for it.
Let's step through it:
1.
inner
is declared as a property on the global object and the value is set toundefined
1.5. the outer
function is created, referencing the global scope as its parent scope
2.
outer
is invoked.3. An execution context is created for
outer
whose scopechainincludesouterVar
and the global object.
…because the chain link of the new execution context references the parent scope of outer
, which is (assigned in 1.5) the global scope. outerVar
is a variable in this new execution context.
4. The value of the
inner
property on the global object is assigned a reference to the function definition.
…and the function's parent scope is set to the execution context of outer
.
5. The execution context for
outer
finishes.(the related scopes are removed? marked for GC?)
…but is not garbage-collected because it is still referenced as the parent scope of the inner
function which is still living (not garbage).
6.
inner
is invoked.7. An execution context is created whose scope
chainincludesinnerVar
and the global object.
The new execution context has a scope chain link to inner
s parent context, which is the execution context created above for the outer
call (which has the chain link to the global scope). innerVar
is a variable in this new execution context.
8.
outerVar
isnotfound in scope
…chain.