javascript – Do variables declared with let and const float in ES6?

Question:

While checking out the ES6 innovations, I noticed that variables declared with var pop up as expected …

console.log(typeof name); // undefined
var name = "John";

… while variables declared with let or const seem to have some problems with hoisting:

console.log(typeof name); // ReferenceError
let name = "John";

and

console.log(typeof name); // ReferenceError
const name = "John";

Does this mean that variables declared with let or const do not bubble up? What's really going on here? Is there any difference between let and const in this case?


Translation of the question: Are variables declared with let or const not hoisted in ES6?

Answer:

tl; dr; quoted from section 13.3.1 Let and Const Declarations

The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.


Variables are created when the containing Lexical Environment is instantiated, but remain inaccessible in any way until their LexicalBinding is evaluated.

So the answer to your question is, yes, let and const pop up, but you can't access them until the actual definition is executed at run-time.


As stated above, these variables cannot be accessed until they are declared. However, things are a little more complicated.

Does this mean that variables declared with let or const do not bubble up? What's really going on here?

In JavaScript, all definitions ( var , let , const , function , function* , class ) bubble up . This means that if a name is defined in an osprey, in this osprey the identifier will always point to a specific variable:

x = "global";
// функциональный скоп:
(function() {
    x; // не "global"

    var/let/… x;
}());
// блочный скоп (не для `var`):
{
    x; // не "global"

    let/const/… x;
}

This is true for both functional and block scopes 1 .

The difference between var / function / function* and let / const / class definitions is in their initialization .
The former are initialized to undefined or by a function (generator) right when the binding is created at the beginning of the scope. However, lexically declared variables remain uninitialized . This means that an attempt to access them will throw a ReferenceError exception. They are initialized. only at the time of execution of let / const / class expressions, everything before that (above) is called the temporal dead zone .

x = y = "global";
(function() {
    x; // undefined
    y; // Reference error: y is not defined

    var x = "local";
    let y = "local";
}());

Note that the expression let y; initializes a variable to undefined , similar to let y = undefined;

The time dead zone is not a syntactic place, but rather the time between the creation of a variable (scope) and initialization. So, it will not be an error to refer to a variable in the code above the definition until this code is executed (for example, the body of a function or simply unreachable code), but an exception will be thrown when trying to access the variable before its initialization, even if the access code is located below the definition ( for example, in the pop-up definition of a function that was called too early).

Is there any difference between let and const in this case?

No, they work exactly the same when viewed from the ascent side. The only difference is that const antes must and can be assigned only in the part of the initializer of the definition ( const one = 1; const one; variant const one; with the subsequent assignment of the value one = 2 not allowed).


1: naturally, var definition only works at the function level


Translations of @thefourtheye and @Bergi's answers

Scroll to Top