Open In App

JavaScript Hoisting

Last Updated : 29 Jan, 2025
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Share
Report
News Follow

Hoisting refers to the behaviour where JavaScript moves the declarations of variables, functions, and classes to the top of their scope during the compilation phase. This can sometimes lead to surprising results, especially when using var, let, const, or function expressions.

  • Hoisting applies to variable and function declarations.
  • Initializations are not hoisted, they are only declarations.
  • ‘var’ variables are hoisted with undefined, while ‘let’ and ‘const’ are hoisted but remain in the Temporal Dead Zone until initialized.

Before going to learn more about Hoisting it’s important first to understand the Temporal Dead Zone

Temporal Dead Zone (TDZ)

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.
JavaScript
hello(); // TypeError: hello is not a function
var hello = function() {
    console.log("Hi!");
};

The variable hello is hoisted, but it is not initialized until the assignment line is reached since it holds a function expression. Thus, calling hello() before its initialization throws a TypeError.

1. Variable Hoisting with var

When you use var to declare a variable, the declaration is hoisted to the top, but its value is not assigned until the code execution reaches the variable’s initialization. This results in the variable being assigned undefined during the hoisting phase.

JavaScript
console.log(a); // undefined
var a = 5;

The declaration var a is hoisted to the top, but a is initialized with undefined. Hence, logging results in undefined.

2. Variable Hoisting with let and const

Unlike var, let and const are also hoisted, but they remain in a Temporal Dead Zone (TDZ) from the start of the block until their declaration is encountered. Accessing them before their declaration will throw a ReferenceError.

JavaScript
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;

The variable is hoisted, but it’s in the Temporal Dead Zone (TDZ) until the declaration line is executed.

3. Function Declaration Hoisting

Function declarations are hoisted with both their name and the function body. This means the function can be called before its definition in the code.

JavaScript
greet(); // "Hello, world!"
function greet() {
    console.log("Hello, world!");
}

The function declaration is hoisted, and the entire function definition is available before its position in the code.

4. Function Expression Hoisting

Function expressions are treated like variable declarations. The variable itself is hoisted, but the function expression is not assigned until the line of execution. This means calling the function before its assignment will result in an error.

JavaScript
hello(); // TypeError: hello is not a function
var hello = function() {
    console.log("Hi!");
};

The variable hello is hoisted, but since it’s a function expression, it’s not initialized until the line is executed.

5. Hoisting with let and const in Functions

Variables declared with let and const inside a function are hoisted to the top of the function’s scope, but they remain in the TDZ. This prevents access to them before they are initialized.

JavaScript
function test() {
    console.log(x); // ReferenceError: Cannot access 'x' before initialization
    let x = 50;
}
test();

The variable x is hoisted inside the function but cannot be accessed until its declaration line due to the TDZ.

6. Hoisting with Classes

Classes are hoisted, but they cannot be accessed before they are declared, resulting in a ReferenceError.

JavaScript
const obj = new MyClass(); // ReferenceError
class MyClass {
    constructor() {
        this.name = "Example";
    }
}

Although the class MyClass is hoisted, it cannot be accessed before its declaration due to the TDZ, which is why the code throws a ReferenceError.

7. Re-declaring Variables with var

With var, you can redeclare a variable within the same scope. This is a unique behavior compared to let and const.

JavaScript
var a = 10;
var a = 20; // No error
console.log(a); // 20

With var, the second declaration overwrites the first one without throwing an error.

8. Accessing Variables Declared Later in Loops

When using var in loops, the loop variable is hoisted to the function or global scope, which can cause unexpected behavior. If you use let, the variable is block-scoped and behaves as expected.

JavaScript
for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // 3, 3, 3
    }, 100);
}

The var i is hoisted, and all setTimeout functions share the same i reference, which results in the value 3 after the loop finishes.

9. Using Hoisted Functions with Parameters

Functions can be hoisted with their parameters, but any parameters passed to the function are still determined by the invocation, not by the hoisting.

JavaScript
test(10); // 10
function test(num) {
    console.log(num);
}

The entire function, including its parameters, is hoisted and available for use before the function’s declaration in the code.

10. Hoisting in Nested Functions

Hoisting works within nested functions as well. Variables declared with var inside a function are hoisted to the top of that function scope.

JavaScript
function outer() {
    console.log(a); // undefined
    var a = 5;
    function inner() {
        console.log(b); // undefined
        var b = 10;
    }
    inner();
}
outer();

Both a and b are hoisted within their respective scopes (outer and inner functions), but their values are not set until the code execution reaches the initialization lines.

Hoisting in JavaScript – FAQ’s

What is hoisting in JavaScript?

Hoisting is the behavior where variable and function declarations are moved to the top of their scope during the compilation phase.

What is the Temporal Dead Zone (TDZ)?

The TDZ refers to the time between entering a scope and the variable’s declaration line, during which accessing variables declared with let or const will result in a ReferenceError.

Can I access variables declared with let before initialization?

No, accessing variables declared with let or const before their initialization will throw a ReferenceError.

What happens when I redeclare a variable with var?

With var, you can redeclare a variable within the same scope, and the last declaration will overwrite the previous one.

Why does hoisting behave differently in loops?

When using var, the loop variable is hoisted outside the loop, leading to unexpected results. With let, the variable is scoped to each iteration, avoiding this issue.



Next Article

Similar Reads

three90RightbarBannerImg
  翻译: