function hoisting like var

Brendan Eich brendan at
Sat Jul 26 06:30:17 PDT 2008

On Jul 26, 2008, at 2:07 PM, Ingvar von Schoultz wrote:

> You can't get away from supporting this:
>       {
>           function a(){}
>           var b = a;
>       }
> ES4 is planning to support function declarations locally
> bound in blocks, so the above is valid ES4 code.
> What you see above is function b() hoisting like var.
> (I said b, not a.)

What you said does not make sense. It's true that var b is hoisted to  
the top of the program or function body. But it is not initialized  
until control flows through the assignment b = a that is part of the  
var declaration. So there is no capture problem.

> There is no far-too-complicated split-scope complexity. There
> is no capturing of variables that haven't been declared yet.
> It's simple, intuitive, well-defined and well-behaved.

Thanks, I agree. But it is not what you proposed. Again, from  
Waldemar's original reply, but with your proposed {{}} interpolated  
and the elided code amended to say what the consequence is:

// outer scope
function c() ...;

// inner scope
   if (foo) {
     const c = 37;
   ... c in your proposal must be hoisted to the {{,
       so it can't be function c -- yet it can't be
       initialized to 37 if foo is "falsy" ...

You could reply that const is new (sort of -- two browsers already  
implement it one way, another treats it as var) and therefore should  
always scope to { or {{, whichever is closer. But the point stands if  
you replace const with function or var and hoist to the {{. Repeating  
the next counter-example, with {{}} changes again, to track your  
proposal since the original exchange with Waldemar:

// outer scope
function c() ...;

// inner scope
   function f() {
     return c;
   a = f();
   if (foo) {
     const c = 37;
   b = f();
   ... just what do a and b hold here? Was f's captured
       variable rebound by the if statement? ...

And so on.

> The above is the /exact/ functionality of function hoisting
> like var, apart from using two names. You can refuse the
> clearer syntax, but you can't refuse the above code and
> functionality.

I think I see the confusion now. Do you believe that in the var b =  
a; code you wrote, both the binding of the var named b *and* its  
initialization with the value of the function object denoted a are  
hoisted? Hoisted up to what point?

Waldemar wrote a while back: "Keep in mind that function assignments  
hoist to the beginning of the scope in which the function is defined,  
so your proposal won't work."

The word "assignment" where "definition" was perhaps more precise  
(function definitions replace extant properties of the same name in  
the variable object, they are not equivalent to assignment  
expressions) may have misled you. From the context and the long- 
standing spec and implementation behavior with functions not in  
blocks or any other sub-statement position, it was clear (I think)  
what was meant, but I can see how this could be confusing.

Assignment expressions and initializers in var statements do not  
hoist or otherwise move in the flow of control.


More information about the Es4-discuss mailing list