Hoisting is a mechanism that makes some types of variables accessible/usable in the code before they are actually declared in the code.
Before execution, code is scanned for variable declarations, and for each variable, a new property is created in the variable environment object. This happens is the creation phase of the execution context.
Hoisting does not work the same for all variable types. Let’s analyze the way hoisting works with function declarations, var variables, let and const variables, and function expressions and arrows.
Technically, let and const variables are hoisted, but their value is set to an uninitialized, as if hoisting was not happening at all. Instead, we say that these variables are placed in a so-called Temporal Dead Zone or TDZ, which makes it unable to access the variables between the beginning of the scope and the place where the variables are declared.
Temporal Dead Zone, let and const
TDZ is the region of the scope in which the variable is defined, but can’t be used in any way. It is as if the variable didn’t even exist.
If we try to access the variable in the TDZ, in this case
job, we get a reference error, saying that we cannot access the variable before initialization.
If we try to access the variable that was actually never even created, in this case
x, we get the different error message saying that the variable is not defined.
This means that the
job is in fact in the TDZ where it is uninitialized, but the engine knows that it will be eventually be initialized, because the engine already read the code before and set the
job variable in the variable environment to uninitialized. Then when the execution reaches the line where the variable is declared, it is removed from the TDZ and it’s then safe to use.
Basically each and every let and const variables get their own Temporal Dead Zone, that starts at the beginning of the scope until the line where it is defined. These variables areonly safe to use after the TDZ.
Why TDZ and Hoisting?
The main reason that TDZ was introduced in ES6 is that it makes it easier to avoid and catch errors. Accessing variables before declaration, a variable set to an undefined, is a bad practice and should be avoided.
Secondly, TDZ makes const variables actually work the way they are supposed to. We can’t reassign const variables, so it is impossible to set them to undefined first, and then assign their real value later. Const should never be reassigned. It’s only assigned when execution actually reaches the declaration.