DEV Community

Cover image for Decoding Hoisting in JS
Annapoorani Kadhiravan
Annapoorani Kadhiravan

Posted on

Decoding Hoisting in JS

One of the most confusing concepts for JavaScript beginners is Hoisting. Many developers coming from languages like Java, C, or Python often wonder:

  • How can a function be called before it is declared?
  • Why does JavaScript print undefined instead of throwing an error?
  • Why do let and const behave differently from var?

To answer these questions, we need to understand how JavaScript executes code behind the scenes.


What is Hoisting?

Hoisting is JavaScript's behavior of allocating memory for variables and functions before executing the code.

In simple words:

JavaScript scans the entire program first, creates memory for variables and functions, and then starts executing the code line by line.

Because of this, some variables and functions can be accessed before they appear in the source code.


Does JavaScript Actually Move Code?

No.

Nothing physically moves to the top.

Hoisting is simply a conceptual way to explain JavaScript's internal execution process.


JavaScript Execution Phases

JavaScript executes code in two phases:

1. Memory Creation Phase

During this phase:

  • Variables declared using var are initialized with undefined.
  • Function declarations are stored completely in memory.
  • Variables declared using let and const are created but remain inaccessible.

2. Execution Phase

After memory allocation, JavaScript executes statements one by one.


Variable Hoisting with var

Consider:

console.log(x);

var x = 10;
Enter fullscreen mode Exit fullscreen mode

Output

undefined
Enter fullscreen mode Exit fullscreen mode

Many beginners expect:

10
Enter fullscreen mode Exit fullscreen mode

but JavaScript internally behaves as:

var x;

console.log(x);

x = 10;
Enter fullscreen mode Exit fullscreen mode

During memory creation:

x → undefined
Enter fullscreen mode Exit fullscreen mode

During execution:

  1. Print undefined
  2. Assign 10 to x

Why Does It Print Undefined?

Because only the declaration:

var x;
Enter fullscreen mode Exit fullscreen mode

is hoisted.

The assignment:

x = 10;
Enter fullscreen mode Exit fullscreen mode

remains in its original place.


Variable Hoisting with let

console.log(age);

let age = 25;
Enter fullscreen mode Exit fullscreen mode

Output

ReferenceError:
Cannot access 'age' before initialization
Enter fullscreen mode Exit fullscreen mode

Variable Hoisting with const

console.log(pi);

const pi = 3.14;
Enter fullscreen mode Exit fullscreen mode

Output

ReferenceError
Enter fullscreen mode Exit fullscreen mode

What is Temporal Dead Zone (TDZ)?

Variables declared with let and const are hoisted but remain inside a region called the Temporal Dead Zone.

The TDZ starts from the beginning of the scope and ends when the variable is initialized.

Example:

console.log(a);

let a = 10;
Enter fullscreen mode Exit fullscreen mode

Here:

TDZ begins
↓
console.log(a)
↓
ReferenceError
↓
let a = 10
↓
TDZ ends
Enter fullscreen mode Exit fullscreen mode

Function Hoisting

Functions declared using function declarations are completely hoisted.

Example:

greet();

function greet()
{
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

Output

Hello
Enter fullscreen mode Exit fullscreen mode

Internally:

function greet()
{
    console.log("Hello");
}

greet();
Enter fullscreen mode Exit fullscreen mode

Why Are Functions Fully Hoisted?

JavaScript stores the entire function in memory during the memory creation phase.

Therefore, the function becomes available even before its declaration appears in the code.


Function Expression Hoisting

Consider:

greet();

var greet = function()
{
    console.log("Hello");
};
Enter fullscreen mode Exit fullscreen mode

Output

TypeError: greet is not a function
Enter fullscreen mode Exit fullscreen mode

Internally:

var greet;

greet();

greet = function()
{
    console.log("Hello");
};
Enter fullscreen mode Exit fullscreen mode

At the time of function call:

greet = undefined
Enter fullscreen mode Exit fullscreen mode

Thus:

undefined()
Enter fullscreen mode Exit fullscreen mode

causes an error.


Arrow Function Hoisting

hello();

const hello = () => {
    console.log("Hi");
};
Enter fullscreen mode Exit fullscreen mode

Output

ReferenceError
Enter fullscreen mode Exit fullscreen mode

Since const variables remain inside the Temporal Dead Zone, the function cannot be accessed before initialization.


Hoisting Comparison Table

Declaration Type Hoisted Initial Value
var Yes undefined
let Yes TDZ
const Yes TDZ
Function Declaration Yes Entire Function
Function Expression Variable only undefined
Arrow Function Variable only TDZ

Hoisting vs Undefined

Many beginners confuse these two terms.

Hoisting

The process of allocating memory before execution.

Undefined

The default value assigned to variables declared using var.

Example:

console.log(num);

var num = 100;
Enter fullscreen mode Exit fullscreen mode

Output:

undefined
Enter fullscreen mode Exit fullscreen mode

because internally:

var num;

console.log(num);

num = 100;
Enter fullscreen mode Exit fullscreen mode

Why Does JavaScript Use Hoisting?

JavaScript separates:

  1. Memory allocation
  2. Code execution

This design provides flexibility and supports features like recursion and function reuse.


Advantages of Hoisting

1. Allows Function Calls Before Declaration

greet();

function greet()
{
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

Output:

Hello
Enter fullscreen mode Exit fullscreen mode

2. Supports Recursion

function factorial(n)
{
    if(n === 1)
        return 1;

    return n * factorial(n - 1);
}
Enter fullscreen mode Exit fullscreen mode

Because the function already exists in memory, it can call itself.


3. Improves Code Organization

Example:

main();

function main()
{
    greet();
}

function greet()
{
    console.log("Welcome");
}
Enter fullscreen mode Exit fullscreen mode

Functions can be organized logically without worrying about order.


Should We Rely on Hoisting?

Generally, No.

Although this works:

greet();

function greet()
{
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

it is better to write:

function greet()
{
    console.log("Hello");
}

greet();
Enter fullscreen mode Exit fullscreen mode

This improves:

  • Readability
  • Maintainability
  • Debugging

Common Interview Questions

Is let hoisted?

Yes.

But it remains inside the Temporal Dead Zone.


Is const hoisted?

Yes.

Like let, it stays in the Temporal Dead Zone.


Are functions hoisted?

Function declarations are completely hoisted.


Are arrow functions hoisted?

No.

Only the variable declaration is hoisted.


Why does var print undefined?

Because var variables are initialized with undefined during memory creation.


Difference Between Hoisting and Undefined

Hoisting Undefined
Memory allocation process Default value assigned to var variables
Happens before execution Seen during execution
Applies to variables and functions Applies only to variables

Tips

✔ Declare variables before using them.

✔ Prefer let and const over var.

✔ Do not intentionally depend on hoisting.

✔ Write function declarations before function calls for better readability.

✔ Use meaningful variable names.


Summary

  • Hoisting is JavaScript's memory allocation behavior.
  • Variables declared with var are initialized with undefined.
  • let and const are hoisted but remain inside the Temporal Dead Zone.
  • Function declarations are fully hoisted.
  • Function expressions and arrow functions are not completely hoisted.
  • Hoisting improves flexibility, but relying on it is not recommended.

Reference

https://www.programiz.com/javascript/hoisting
https://www.w3schools.com/js/js_hoisting.asp
https://www.geeksforgeeks.org/javascript/javascript-hoisting/
https://medium.com/@javvadirupasri8/decoding-javascript-hoisting-a-must-know-concept-for-interviews-c4e23438e93e

Top comments (0)