JavaScript Notes
Master JavaScript hoisting: how var, let, const, and function declarations are hoisted, Temporal Dead Zone, creation vs execution phase, and interview Q&A.
What is Hoisting?
Hoisting is JavaScript's behavior of processing declarations before code executes. During the Creation Phase of an Execution Context, the engine scans all declarations and registers them in memory — before a single line runs.
This is why you can call a function declared with function keyword before its definition appears in the file.
One-liner: Hoisting means JavaScript "registers" declarations at the top of their scope before executing — but only declarations, not assignments.
Creation Phase vs Execution Phase
Hoisting Behavior by Declaration Type
| Declaration | Hoisted? | Initial Value | Usable Before Declaration? |
|---|---|---|---|
var | ✅ Yes | undefined | ✅ Yes (but undefined) |
let | ✅ Yes | TDZ | ❌ No (ReferenceError) |
const | ✅ Yes | TDZ | ❌ No (ReferenceError) |
function declaration | ✅ Yes | Full function | ✅ Yes (fully works) |
function expression (var) | ✅ Partially | undefined | ❌ No (TypeError) |
class | ✅ Yes | TDZ | ❌ No (ReferenceError) |
| Arrow function | ✅ Partially | undefined (if var) | ❌ No |
var Hoisting
console.log(message); // undefined — NOT ReferenceError
var message = "Hello, World!";
console.log(message);undefined Hello, World!
What the engine sees (conceptually):
var message; // ← hoisted declaration (undefined)
console.log(message); // undefined
message = "Hello, World!"; // assignment stays in place
console.log(message); // Hello, World!Function Declaration Hoisting
sayHello("Priya"); // Works! Called before definition
function sayHello(name) {
console.log(`Hello, ${name}!`);
}Hello, Priya!
Function declarations are fully hoisted — the entire function body is available from the start of scope.
Function Expression — NOT Fully Hoisted
greet("Aman"); // ❌ TypeError: greet is not a function
var greet = function(name) {
console.log(`Hi, ${name}!`);
};TypeError: greet is not a function
Why? var greet is hoisted as undefined. Calling undefined() throws TypeError. The function is only assigned when execution reaches that line.
let and const — Temporal Dead Zone (TDZ)
console.log(x); // ❌ ReferenceError — TDZ
let x = 10;
console.log(x); // ✅ 10ReferenceError: Cannot access 'x' before initialization
The TDZ exists to prevent the confusing undefined behavior of var. Accessing before initialization is a programming error — TDZ turns it into a clear error.
Class Hoisting — TDZ
Classes also have TDZ:
const obj = new MyClass(); // ❌ ReferenceError
class MyClass {
constructor() {
this.name = "test";
}
}ReferenceError: Cannot access 'MyClass' before initialization
Hoisting in Functions (Inner Scope)
Hoisting is per-scope, not just global:
function outer() {
console.log(inner); // undefined — var hoisted within outer's scope
var inner = "I am inner";
console.log(inner);
}
outer();undefined I am inner
Practical Example — Hoisting Bug
3 3 3
Why? var i is function-scoped (not block-scoped). By the time setTimeout fires, the loop is done and i = 3. All three closures share the same i.
0 1 2
Hoisting Order Priority
When multiple declarations exist for the same name:
[Function: foo] variable
Rule: Function declarations take priority over var declarations during hoisting. But after assignment at line 3, foo holds the string.
Common Mistakes
❌ Mistake 1 — Relying on var Hoisting Intentionally
// WRONG — leads to confusing undefined values
function showUser() {
if (condition) {
var name = "Riya";
}
console.log(name); // undefined if condition is false — confusing!
}// CORRECT — use let/const for predictable scoping
function showUser() {
if (condition) {
let name = "Riya";
console.log(name);
}
}❌ Mistake 2 — Calling Arrow Functions Before Assignment
TypeError: greet is not a function
Arrow functions assigned to var are hoisted as undefined, not as functions.
❌ Mistake 3 — Thinking let/const Are NOT Hoisted
let x = "outer";
function test() {
console.log(x); // NOT "outer" — ReferenceError (TDZ)!
let x = "inner";
}
test();ReferenceError: Cannot access 'x' before initialization
let x IS hoisted to the top of test(), which is why the outer x isn't accessible — the inner x is in TDZ. This proves let is hoisted (just stays in TDZ until its declaration line).
Interview Questions 🎯
Q1. What is hoisting in JavaScript?
Hoisting is JavaScript's behavior of registering (not executing) declarations during the Creation Phase of an execution context, before any code runs. var declarations are initialized to undefined, function declarations are fully available, and let/const are in the Temporal Dead Zone.
Q2. What is the difference between var, let, and const hoisting?
var: hoisted and initialized toundefined— accessible butundefinedbefore assignmentlet: hoisted but in TDZ — accessing before declaration throwsReferenceErrorconst: same aslet(TDZ) — additionally must be initialized in the same statement
Q3. What is the Temporal Dead Zone (TDZ)?
The TDZ is the period between when a let/const variable is registered (start of scope) and when execution reaches its declaration line. Accessing a variable in TDZ throws ReferenceError: Cannot access 'x' before initialization.
Q4. Are function expressions hoisted?
The variable name is hoisted (as undefined if var), but the function body is NOT. So calling a var-assigned function expression before assignment throws TypeError: functionName is not a function.
Q5. Why do function declarations take priority over var in hoisting?
During the creation phase, function declarations are processed first and stored fully. When a var declaration with the same name is encountered, it does not override the function. Only the actual var = ... assignment at execution time can overwrite it.
Q6. What is the classic var-in-loop hoisting bug?
var i is function-scoped, so all three closures share the same i, which is 3 by the time setTimeout fires. Fix: use let.
Q7. Is there hoisting inside functions?
Yes. Every execution context (including function contexts) has its own hoisting. Declarations inside a function are hoisted to the top of that function's scope, not the global scope.
Q8. Are classes hoisted?
Classes are hoisted but remain in the Temporal Dead Zone, just like let and const. Accessing a class before its declaration throws ReferenceError.
Key Takeaways 🔑
- Hoisting is the Creation Phase behavior: declarations are registered before execution
var→ hoisted asundefined— usable but confusing before assignmentlet/const→ hoisted into TDZ — throwsReferenceErrorif accessed earlyfunctiondeclarations → fully hoisted — can be called anywhere in scopefunctionexpressions (var) → hoisted asundefined— calling early =TypeError- Classes → hoisted into TDZ like
let - In the
varloop bug, useletto get a fresh binding per iteration - Modern best practice: always use
let/const, declare before use
Summary
Hoisting is JavaScript's two-phase execution model in action: during the Creation Phase, all declarations in a scope are registered before any code runs. var declarations are initialized to undefined (accessible but confusing), let and const are registered but placed in the Temporal Dead Zone (TDZ) where access throws ReferenceError, and function declarations are fully available from the start. Understanding hoisting explains the classic undefined var bugs, the var loop closure problem, and why let/const were introduced. The modern best practice is to declare variables before use, use let/const instead of var, and rely on function declaration hoisting only when intentional.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Hoisting - Complete Guide with var, let, const & Functions.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, advanced, hoisting, javascript hoisting - complete guide with var, let, const & functions
Related JavaScript Master Course Topics