Hoisting
Var vs Let vs Const
| Feature | var | let | const |
| Scope | Function | Block | Block |
| Hoisted | Yes | Yes (TDZ) | Yes (TDZ) |
| Initialized on hoist | Yes | No | No |
| Re-declaration | Yes | No | No |
| Re-assignment | Yes | Yes | No |
| Global object | Yes | No | No |
First, the Mental Model (Critical)
Before definitions, you must understand how JavaScript executes code.
JavaScript execution happens in two phases:
Phase 1: Memory Creation Phase
Variables are allocated memory
Function declarations are stored entirely
No code is executed
Phase 2: Execution Phase
Code runs line by line
Variables get assigned actual values
Hoisting happens in Phase 1.
What Is Hoisting?
Hoisting is JavaScript’s behavior of moving variable and function declarations to the top of their scope during the memory creation phase.
Important clarification:
Only declarations are hoisted
Assignments are NOT hoisted
Hoisting with var
Example
console.log(a);
var a = 10;
What You See
undefined
What Actually Happens Internally
Memory Creation Phase
var a; // initialized with undefined
Execution Phase
console.log(a); // undefined
a = 10;
✔ This is why var gives undefined, not an error.
Hoisting with let and const (Key Difference)
console.log(b);
let b = 20;
Output:
ReferenceError: Cannot access 'b' before initialization
❗ Important:
letandconstARE hoistedBut they are NOT initialized
This leads us to the Temporal Dead Zone.
Temporal Dead Zone (TDZ) — Proper Definition
The Temporal Dead Zone is:
The time between scope creation and variable initialization during which accessing the variable throws a
ReferenceError.
TDZ applies to:
letconstclass
Visualizing TDZ
{
// TDZ starts
console.log(x); // ❌ ReferenceError
let x = 10;
// TDZ ends
}
Timeline:
Scope created ──▶ TDZ ──▶ Initialization ──▶ Usage allowed
Why TDZ Exists (Interview Gold)
TDZ was introduced to:
Prevent bugs caused by accessing variables before declaration
Enforce clean, predictable code
Replace unsafe
varbehavior
Interview-grade explanation:
“TDZ ensures variables are used only after they are declared, preventing logical errors.”
Global Scope Behavior (Browser-Specific Question)
var a = 10;
let b = 20;
console.log(window.a); // 10
console.log(window.b); // undefined
Explanation:
varattaches to the global objectletandconstdo NOT
This prevents accidental global pollution.
Loop Behavior (Very Common Interview Trap)
Using var
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
Output:
3 3 3
Using let
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
Output:
0 1 2
Why?
letcreates a new block scope per iteration