Hoisting in JavaScript is a mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase, before the code is executed. This means you can use variables and call functions before they are explicitly declared in your code
Here's how hoisting works for different types of declarations:
var declarations: Variables declared with var
are hoisted to the top of their scope and are initialized with undefined. This means you can access a var variable before its declaration, but its value will be undefined until the line of code where it's assigned a value is executed.
console.log(myVar); // Output: undefined
var myVar = 10;
console.log(myVar); // Output: 10
Hoisting let
and const
variables
Variables declared with let
and const
are also hoisted, but they are not initialized. Instead, they enter a "Temporal Dead Zone" (TDZ) from the beginning of their scope until their declaration line is reached. Attempting to access a let or const variable within the TDZ will result in a ReferenceError
.
// console.log(myLet); // This would throw a ReferenceError (TDZ)
let myLet = 20;
console.log(myLet); // Output: 20
The Temporal Dead Zone in JavaScript
The Temporal Dead Zone (TDZ) is a critical concept in JavaScript hoisting. It refers to the period between the entering of a scope (such as a function or block) and the actual initialization of a variable declared with let
or const
. During this time, any reference to the variable before its initialization will throw a ReferenceError.
How does the TDZ Work?
Variables declared with let
and const
are hoisted to the top of their scope, but they are not initialized until their declaration line is reached.
Any attempt to access these variables before their declaration will result in an error.
The TDZ exists only for variables declared using let
and const
. Variables declared with var
do not have this issue, as they are hoisted and initialized to undefined
.
console.log(myName) // temporal dead zone for myName,
//ReferenceError: Cannot access 'myName' before initialization
// temporal dead zone for myName
// temporal dead zone for myName
// temporal dead zone for myName
// temporal dead zone for myName
// temporal dead zone for myName
// temporal dead zone for myName
let myName = "Kithiyon" // now accessible
// now accessible
// now accessible
// now accessible
Function declarations: Function declarations are fully hoisted, meaning both the function name and its definition are moved to the top of their scope. This allows you to call a function before its declaration in the code.
function printHello() {
console.log("hello")
}
printHello()
// hello
Here, we declare printHello, and we execute the function just after the line it was declared. No errors; everything works!
printHello()
// hello
function printHello() {
console.log("hello")
}
Here, we execute printHello before the line the function was declared. And everything still works without errors. What happened here? Hoisting.
Before the interpreter executes the whole code, it first hoists (raises, or lifts) the declared function to the top of the scope it is defined in. In this case, printHello is defined in the global scope, so the function is hoisted to the top of the global scope. Through hoisting, the function (including the logic) becomes accessible even before the line it was declared in the code.
Function expressions and arrow functions:
These are treated like variable declarations. If declared with var, they will be hoisted and initialized to undefined. If declared with let or const, they will be in the TDZ.
// myFuncExpression(); // This would throw a TypeError if declared with var (undefined is not a function)
// myArrowFunc(); // This would throw a ReferenceError if declared with let/const (TDZ)
var myFuncExpression = function() {
console.log("Hello from function expression!");
};
myFuncExpression(); // Output: Hello from function expression!
const myArrowFunc = () => {
console.log("Hello from arrow function!");
};
myArrowFunc(); // Output: Hello from arrow function!
In summary, while hoisting moves declarations to the top, the initialization behavior differs between var
and let/const
, and function
declarations are fully hoisted, enabling early invocation. Understanding hoisting is crucial for writing predictable and error-free JavaScript code.
Top comments (0)