JavaScript Hoisting
Hoisting
Hoisting is a default feature in JavaScript where all declarations are moved to the top of their containing scope(script or current function). Hoisting allows us to use variables before they are declared.
Hoisting with "var"
Variables in JavaScript can be declared using var, let, and const statements.
Let us see a quick example of how hoisting works using variables declared with the "var" keyword:
console.log(name); //logs undefined
var name = "John"; //initialize name
In the above code, the variable "name" is called before it is initialized. Something important that we should notice is we do not get an error, instead, we got a datatype of undefined.
Why?
The JavaScript interpreter hoists the defined variable "name" to the top of the containing scope. The value "John" it is initialized with, is not recognized as it is not hoisted along with the variable.
Let's have another example:
name = "John";
console.log(name); // logs John
var name;
In this example, we can see that the "name" variable is assigned a value "John" but not declared until after it is logged into the console. The var keyword is hoisted to the top of the scope and the variable, it is attached to already has a value assigned to it before it is logged. Therefore it gives us the value of "John".
It is an unusual behavior to be able to access variables before they are declared. It can lead to errors or unexpected scenarios. Some of the issues concerning the usage of "var" led to the introduction of "let" and "const" keywords, introduced in ECMAScript 2015.
Hoisting with "let" and "const"
Like the var keyword, "let" and "const" is hoisted to the top of the containing scope. The main difference is in their initialization. While the "var" keyword is initialized with a default value(undefined), the "let" and "const" keywords are not initialized. Therefore, accessing a "let" or "const" variable before declaration results in a ReferenceError:
console.log(name); //Uncaught ReferenceError: Cannot access 'name' before initialization
const name = "Paul"; //same as initializing with let
Notice the error message?
It indicates that the interpreter understands that the variable is initialized somewhere in the code but cannot access it. It clearly shows that the "let" and "const" keywords are hoisted at the top of the scope but not initialized.
Temporal Dead Zone(TDZ)
The Temporal Dead Zone occurs at the start of a variable's containing scope and ends when it is declared. Accessing a variable in this zone results in a ReferenceError.
The reason we got a ReferenceError in the previous example is that we tried to access the let/const variable in its TDZ:
//start of name's TDZ
console.log(name); // ReferenceError because of TDZ
const name = "Paul"; // end of name's TDZ
Using Hoisting in JavaScript
Due to the confusion and errors that may arise using hoisting, it is usually advised to avoid using variables before declaring them. Using let and const keywords enforces this.