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