Body-level inner function declarations interaction with the let "temporal dead zone"
It is my understanding that in both cases the declaration are valid but calling inner before "let x" will result in an exception.
On Jul 18, 2014, at 5:34 PM, Shu-yu Guo wrote:
Am I correct in understanding that body-level inner functions hoist both declaration and initialization to the top of the outer function?
correct.
That is, given the following snippet:
Listing 1
function outer() { let x; function inner() { x = 2; } }
Is it equivalent to the following?
yes, for the purpose of your question. Using a var has some other implications that are not relevant to your question.
Listing 2
function outer() { var inner = function inner() { x = 2; }; let x; }
If so, that means in inner functions, all free uses of let-declared variables from outer lexical scopes are in the ES6 "temporal dead zone". More problematically, it means that there is no-easy-to-compute dominance relation (i.e., at parse time) to omit the dead zone checks for any upvar uses of let bindings, even though textually, listing 1 looks like the initialization dominates all uses.
You should be able to eliminate the TDZ checks in inner if all references to inner are dominated by initializing declarations of all upvars referenced from inner.
For example:
Listing 3
function outer() {
let x;
function inner() {
x = 2; // TDZ check could be eliminated because x is initialized before any reference is made to inner
}
inner(); //the initializing let x dominates this reference.
}
Listing 4
function outer() {
foo(inner); //x not yet initialized
let x;
function inner() {
x = 2; // TDZ necessary because a reference to inner dominates the initializing declaration of x
}
}
Am I correct in understanding that body-level inner functions hoist both declaration and initialization to the top of the outer function?
That is, given the following snippet:
Listing 1
function outer() { let x; function inner() { x = 2; } }
Is it equivalent to the following?
Listing 2
function outer() { var inner = function inner() { x = 2; }; let x; }
If so, that means in inner functions, all free uses of let-declared variables from outer lexical scopes are in the ES6 "temporal dead zone". More problematically, it means that there is no-easy-to-compute dominance relation (i.e., at parse time) to omit the dead zone checks for any upvar uses of let bindings, even though textually, listing 1 looks like the initialization dominates all uses.