Question

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?

http://jsfiddle.net/6zvsh/

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:

  1. inner is declared as a property on the global object and the value is set to undefined
  2. outer is invoked.
  3. An execution context is created for outer whose scope chain includes outerVar and the global object.
  4. The value of the inner property on the global object is assigned a reference to the function definition.
  5. The execution context for outer finishes. (the related scopes are removed? marked for GC?)
  6. inner is invoked.
  7. An execution context is created whose scope chain includes innerVar and the global object.
  8. outerVar is not found in scope

Can someone please explain why outerVar is defined?

Was it helpful?

Solution

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 to undefined

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 scope chain includes outerVar 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 chain includes innerVar and the global object.

The new execution context has a scope chain link to inners 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 is not found in scope

…chain.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top