Hoisting behaviour of 'const' and 'let'

David-Sarah Hopwood david.hopwood at industrial-designers.co.uk
Sun Oct 12 14:13:22 PDT 2008

Yuh-Ruey Chen wrote:
> David-Sarah Hopwood wrote:
>> Mark S. Miller wrote:
>>> {
>>>     .... f(); ...
>>>     const x = 3;
>>>     function f() { ... x ... }
>>> }
>> <snip>
>> 3) we allow f to refer to x, but disallow the reference to f outside the
>>    scope of x.
>> More generally,
>>  - if a function refers to a 'let' or 'const' variable, its effective
>>    scope is intersected with the scope of that variable.
>> This rule is simple, easy to explain and motivate, does not
>> unnecessarily reject "good" programs, and is straightforward to work
>> around in cases where the program would be dynamically safe.
>> If it is used then no read or write barriers are required.
> To clarify, would this proposed rule also invalidate the following example?
> {
>     var g = f;   // is this what you mean by "reference to f"?
>     g();
>     const x = 3;
>     function f() { ... x ... }
> }

Yes. Since 'x' is a free identifier of 'f' and there exists a (single)
'const' or 'var' declaration of 'x' in the same block, 'f' is not in
scope until after that declaration of x.

(To fill in some details: multiple initializers are treated as if they
were separate statements, e.g. "var a = x, b = y;" is equivalent to
"var a = x; var b = y;". A variable is not in scope in its own initializer.
If there are multiple declarations of a 'const' or 'let' variable x in
a block, then no function in that block can refer to x, since it is not
clear which x is meant.)

> Then what about this example?
> // global scope
> if (cond)   // suppose it's true
>     y = 'f';

I think you meant
      y = f;

> this[y]();
> const x = 3;
> function f() { ... x ... }
> This is a case where static analysis would not find the premature call
> to f().

Yes it would.

If the program is not fully known in advance (e.g. the statements are
being entered in a REPL, or the declaration of 'f' is in a later <script>
block than the 'y = f;'), then it cannot have been fully "processed for
function declarations" before the assignment to y, so y will have the
value undefined (assuming there was no previous definition of 'f'), and
"this[y]();" will throw without referencing x.

Alternatively, if the program is completely known in advance, then it
can be fully processed for function declarations, but in that case it is
statically invalid because f is referenced outside its scope.

David-Sarah Hopwood

More information about the Es-discuss mailing list