Skip to main content

How Does Hoisting Work in JavaScript?

Answer​

Hoisting is JavaScript's behavior of moving declarations to the top of their scope during the compilation phase, before code execution.

Hoisting Visualization​

var Hoisting​

// What you write
console.log(name); // undefined (not error!)
var name = "John";
console.log(name); // "John"

// How JavaScript interprets it
var name; // Declaration hoisted
console.log(name); // undefined
name = "John"; // Assignment stays in place
console.log(name); // "John"

let and const Hoisting​

// let and const are hoisted BUT not initialized
// They exist in "Temporal Dead Zone" (TDZ)

console.log(name); // ReferenceError: Cannot access before initialization
let name = "John";

console.log(age); // ReferenceError: Cannot access before initialization
const age = 25;

Temporal Dead Zone (TDZ)​

{
// TDZ starts here for 'x'
console.log(x); // ReferenceError

let x = 10; // TDZ ends
console.log(x); // 10
}

Function Hoisting​

// Function declarations are fully hoisted
sayHello(); // "Hello!" (works!)

function sayHello() {
console.log("Hello!");
}

// Function expressions are NOT hoisted
sayGoodbye(); // TypeError: sayGoodbye is not a function

var sayGoodbye = function () {
console.log("Goodbye!");
};

Arrow Functions​

// Arrow functions behave like function expressions
greet(); // TypeError: greet is not a function

var greet = () => {
console.log("Hi!");
};

// With let/const - even worse (TDZ)
welcome(); // ReferenceError: Cannot access before initialization

const welcome = () => {
console.log("Welcome!");
};

Class Hoisting​

// Classes are hoisted but remain in TDZ
const p = new Person(); // ReferenceError

class Person {
constructor(name) {
this.name = name;
}
}

Hoisting Priority​

// Function declarations take precedence over var
console.log(typeof foo); // "function"

var foo = "variable";

function foo() {
return "function";
}

console.log(typeof foo); // "string" (var assignment happened last)

Practical Example​

// Why this causes confusion
var count = 10;

function example() {
console.log(count); // undefined (not 10!)
var count = 20;
console.log(count); // 20
}

example();

// Because JavaScript sees it as:
function example() {
var count; // Hoisted declaration
console.log(count); // undefined
count = 20;
console.log(count); // 20
}

Best Practices​

// ✅ Good: Declare at the top
function example() {
let count = 0;
const MAX = 100;

// Use variables here
}

// ✅ Good: Use let/const to catch TDZ errors
// ❌ Avoid: Relying on var hoisting

// ✅ Good: Declare functions before calling
function greet() {
console.log("Hi");
}
greet();

// ❌ Avoid: Calling functions before declaration

Summary Table​

DeclarationHoisted?Initialized?Can Use Before?
var✅ Yesundefined⚠️ undefined
let✅ Yes❌ No (TDZ)❌ ReferenceError
const✅ Yes❌ No (TDZ)❌ ReferenceError
function✅ Yes✅ Yes✅ Yes
class✅ Yes❌ No (TDZ)❌ ReferenceError

Key Points​

  • All declarations are hoisted to scope top
  • var is initialized with undefined
  • let/const are in TDZ until initialization
  • Function declarations are fully hoisted
  • Function expressions follow var/let/const rules
  • Best practice: Declare before use, prefer let/const