Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are variables declared with let or const hoisted?

I have been playing with ES6 for a while and I noticed that while variables declared with var are hoisted as expected...

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

...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 are not hoisted? What is really going on here? Is there any difference between let and const in this matter?

like image 947
Luboš Turek Avatar asked Jul 04 '15 10:07

Luboš Turek


People also ask

Why VAR is hoisted and let not?

var is declared and initialized during hoisting. let and const are only declared during hoisting, not initialized. Accessing uninitialized variables result in ReferenceError . Prefer let over var , wherever possible to avoid the confusion arising due to hoisting.

Does hoisting work for Let?

Yes, variables declared with let and const are hoisted. Where they differ from other declarations in the hoisting process is in their initialization. During the compilation phase, JavaScript variables declared with var and function are hoisted and automatically initialized to undefined .

Does hoisting work with all the variables and why?

In JavaScript, Hoisting is the default behavior of moving all the declarations at the top of the scope before code execution. Basically, it gives us an advantage that no matter where functions and variables are declared, they are moved to the top of their scope regardless of whether their scope is global or local.

Can variables using let or const be re declared?

var variables can be updated and re-declared within its scope; let variables can be updated but not re-declared; const variables can neither be updated nor re-declared. They are all hoisted to the top of their scope.


1 Answers

@thefourtheye is correct in saying that these variables cannot be accessed before they are declared. However, it's a bit more complicated than that.

Are variables declared with let or const not hoisted? What is really going on here?

All declarations (var, let, const, function, function*, class) are "hoisted" in JavaScript. This means that if a name is declared in a scope, in that scope the identifier will always reference that particular variable:

x = "global"; // function scope: (function() {     x; // not "global"      var/let/… x; }()); // block scope (not for `var`s): {     x; // not "global"      let/const/… x; } 

This is true both for function and block scopes1.

The difference between var/function/function* declarations and let/const/class declara­tions is the initialisation.
The former are initialised with undefined or the (generator) function right when the binding is created at the top of the scope. The lexically declared variables however stay uninitialised. This means that a ReferenceError exception is thrown when you try to access it. It will only get initialised when the let/const/class statement is evaluated, everything before (above) that 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"; }()); 

Notice that a let y; statement initialises the variable with undefined like let y = undefined; would have.

The temporal dead zone is not a syntactic location, but rather the time between the variable (scope) creation and the initialisation. It's not an error to reference the variable in code above the declaration as long as that code is not executed (e.g. a function body or simply dead code), and it will throw an exception if you access the variable before the initialisation even if the accessing code is below the declaration (e.g. in a hoisted function declaration that is called too early).

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

No, they work the same as far as hoisting is regarded. The only difference between them is that a constant must be and can only be assigned in the initialiser part of the declaration (const one = 1;, both const one; and later reassignments like one = 2 are invalid).

1: var declarations are still working only on the function level, of course

like image 95
Bergi Avatar answered Sep 27 '22 17:09

Bergi