Reputation: 18600
Notice the closure example below:
<script>
function foo() {
var x = 1;
function bar() {
var y = 2;
alert(x + y);
}
return bar;
}
var dummy = foo(); // Assign variable binding "dummy" to a reference of the "bar" function.
dummy(); // When entering the "bar" function code, will it go through the execution context creation phase?
</script>
When invoking the dummy variable binding (which will execute the "bar" function code), is a new execution context created? The ECMAScript Specification specifies what happens when entering function code, but since this is a reference to a function/closure, I wasn't sure if it had to go through the whole execution context creation/binding phase again.
Upvotes: 3
Views: 218
Reputation: 39168
Good question. Let's see what's going on:
dummy()
is a Function Call (11.2.3)
See step #8 "Return the result of calling the [[Call]] internal method on func, providing thisValue as the this value and providing the list argList as the argument values."
So dummy.[[Call]]
is invoked. Moving onto 13.2.1 ([[Call]]
).
Let funcCtx be the result of establishing a new execution context for function code using the value of F's [[FormalParameters]] internal property, the passed arguments List args, and the this value as described in 10.4.3.
So dummy()
does in fact create new execution context as described in 10.4.3.
Now that dummy
's function code is executed, NewDeclarativeEnvironment is created as per step #5 in 10.4.3 passing dummy.[[Scope]]
dummy
is just a reference to bar
, so dummy.[[Scope]]
is bar.[[Scope]]
. And bar.[[Scope]]
was defined at the moment when foo
executed (a line earlier), naturally creating functions for each function declaration within (including bar
).
bar.[[Scope]]
is essentially a chain consisting of [global environment]
and [foo VE]
(Variable Environment). So at the moment of its execution it creates its own VE and uses foo's VE as the outer. Scope chain now consists of [global environment]->[foo VE]->[bar VE]
.
x
is found in var's VE, y
is found in bar's VE, and alert successfully receives 3
as an argument :)
But to answer your original question, yes "entering function code" happens in case of
(function(){ ... })();
and in case of
f();
since both of them essentially call function's [[Call]]. It's just that 1st one is a CallExpression
that consists of FunctionExpression
followed by Arguments
, whereas 2nd one is a CallExpression
that consists of Identifier
followed by Arguments
.
Both still resolve to a function object, which has internal [[Call]] method, which is what gets executed.
Upvotes: 2
Reputation: 1056
I think scope chain is the thing you are looking here:
Every time a function is invoked, it creates a new object to store its local variables, and adds that new object to the stored scope chain to create a new, longer, chain that represents the scope for that function invocation.
For your question yes it will again go through the whole execution context, otherwise how can you return another function from bar() like
function bar() {
var y = 2;
alert(x + y);
return function() {alert('hello');}
}
Upvotes: 0