JavaScript Hoisting
Understand how JavaScript loads variables and functions into memory before running your code, and master the Temporal Dead Zone (TDZ).
1. What is Hoisting?
Hoisting is JavaScript's default behavior of scanning your code and allocating memory for all variables and functions before executing any line of code.
💡 Think of a Teacher Taking Attendance Before Class Starts
Before the lecture begins, the teacher goes through the roster and writes every student's name on the board. When class starts, the teacher already knows who everyone is, even before they raise their hands!
Phase 1: Memory Setup (Creation)
JS scans the file from top to bottom. It registers all variable names and stores entire function definitions into memory.
Phase 2: Code Execution (Running)
JS executes your code line by line from top to bottom, calculating values and assigning them to variables.
2. Function Declarations vs Expressions
Because entire function declarations are saved in memory during Phase 1, you can call them before the line they are written on:
// ✅ Works! Function declarations are hoisted completely with their body:
sayHello(); // "Hello from hoisted function!"
function sayHello() {
console.log("Hello from hoisted function!");
}
// ❌ Fails! Function expressions stored in var are hoisted as undefined:
// sayGoodbye(); // TypeError: sayGoodbye is not a function
var sayGoodbye = function() {
console.log("Goodbye!");
};
// ❌ Fails! let & const are trapped in the Temporal Dead Zone:
// add(2, 3); // ReferenceError: Cannot access 'add' before initialization
const add = (a, b) => a + b;
Hello from hoisted function!
3. How `var`, `let`, and `const` are Hoisted
All three types are hoisted to the top of their scope, but they behave very differently when you try to use them before their declaration line:
`var` = Initialized with `undefined` ⚠️
Accessing var before its line does not crash. It quietly gives you undefined, which can lead to tricky silent bugs.
console.log(user); // undefined
var user = "Alex";
`let` & `const` = Locked in TDZ ✅
Placed in the Temporal Dead Zone (TDZ). Trying to access them throws a clear ReferenceError immediately.
// console.log(role); // ReferenceError!
let role = "Admin";
4. The Temporal Dead Zone (TDZ) Made Simple
The Temporal Dead Zone (TDZ) is simply the time period between entering a block of code and the exact line where a let or const variable is declared:
💡 Think of a Table Reservation at a Restaurant
Your name is on the reservation book (memory is allocated), but you are not allowed to sit at the table until your reservation time arrives (the declaration line). If you try to sit early, the staff stops you (throws a ReferenceError)!
{
// ⛔ START of TDZ for 'price'
// console.log(price); // ❌ ReferenceError: Cannot access 'price' before initialization
let tax = 5;
console.log("Tax is:", tax); // 5
let price = 100; // ✅ END of TDZ for 'price'
console.log("Price is:", price); // 100
}
Tax is: 5 Price is: 100
5. Quick Hoisting Comparison
| Declaration Type | Hoisted to Memory? | Initial Value in Phase 1 | Accessing Before Declaration Line |
|---|---|---|---|
function myFunc() {} |
Yes | Full function body | ✅ Works perfectly! |
var name = "Alex" |
Yes | undefined |
⚠️ Returns undefined (Bug prone) |
let count = 10 |
Yes | Uninitialized (in TDZ) | ❌ Throws ReferenceError |
const max = 100 |
Yes | Uninitialized (in TDZ) | ❌ Throws ReferenceError |
6. Hoisting Interview Deck
Test your knowledge on function hoisting, TDZ traps, local scope shadowing, and declaration vs expression behavior:
7. Practice Challenge
🎯 Coding Challenge: Hoisting & TDZ Handling
1. Call a function sayHi() before its definition line to prove function declaration hoisting.
2. Wrap a read of an uninitialized const myConst in a try...catch block to catch and print the Temporal Dead Zone ReferenceError safely.