JavaScript Hoisting
Hoisting is JavaScript's default behaviour of moving declarations to the top of their scope before execution. Only the declaration is hoisted — not the initialisation.
var Hoisting
var declarations are hoisted and initialised to undefined. You can use a var variable before its declaration line, but its value will be undefined.
var Hoisting Demo
console.log(name); // undefined (hoisted, not an error!)
var name = "Alice";
console.log(name); // "Alice"
// JavaScript processes this as:
// var name; ← hoisted
// console.log(name); ← undefined
// name = "Alice";
// console.log(name); ← "Alice"let and const — Temporal Dead Zone
let and const are also hoisted but NOT initialised. Accessing them before declaration throws a ReferenceError. The gap between hoisting and declaration is called the Temporal Dead Zone (TDZ).
Temporal Dead Zone
// console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;
console.log(x); // 10
// console.log(y); // ReferenceError
const y = 20;
console.log(y); // 20Function Declaration Hoisting
Function declarations are fully hoisted — both the declaration AND the body. You can call them before they appear in the code.
Function Declarations are Fully Hoisted
// Call BEFORE the definition — works!
console.log(greet("Alice")); // "Hello, Alice!"
function greet(name) {
return "Hello, " + name + "!";
}Function Expressions are NOT Hoisted
Function Expression — Not Hoisted
// console.log(square(5)); // TypeError: square is not a function
const square = function(x) {
return x * x;
};
console.log(square(5)); // 25 (works after declaration)| Declaration | Hoisted? | Initialised? | Usable Before? |
|---|---|---|---|
| var | ✓ Yes | ✓ Yes (undefined) | Yes (undefined) |
| let | ✓ Yes | ✗ No (TDZ) | No (ReferenceError) |
| const | ✓ Yes | ✗ No (TDZ) | No (ReferenceError) |
| function decl. | ✓ Yes | ✓ Yes (full body) | Yes (fully works) |
| function expr. | Variable only | ✗ No | No (TypeError) |
📝 Note: Best practice: always declare variables at the top of their scope to avoid confusion around hoisting. Prefer let and const over var.
Exercise:
Which declaration type is hoisted AND initialized with its full body?