JavaScript Notes
Master the difference between var, let, and const in JavaScript. Learn scope, hoisting, temporal dead zone, re-declaration, and when to use each with clear examples.
One of the first decisions you make in JavaScript is how to declare a variable. There are three keywords: var (old), let (modern), and const (modern). Understanding the differences is critical because they have fundamentally different behaviors around scope, hoisting, and reassignment.
Real World Analogy
Think of three types of containers:
constis like a sealed bottle — you can't pour it out and replace it with something else. But you can still drink from it (read its value) or add flavor drops (mutate properties of objects/arrays).letis like a regular cup — you can pour it out and fill it with something else (reassign) whenever you want.varis like a magic cup that teleports to the kitchen (function scope) — no matter where in the kitchen you use it, it's accessible from anywhere in that kitchen. This can cause unexpected behavior.
The Master Comparison Table
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (initialized as undefined) | Yes (in TDZ — unusable) | Yes (in TDZ — unusable) |
| Re-declaration | ✅ Allowed | ❌ Error | ❌ Error |
| Reassignment | ✅ Allowed | ✅ Allowed | ❌ Error |
| Global property (top-level) | ✅ Creates window.x | ❌ No | ❌ No |
| Introduced in | ES1 (1995) | ES6 (2015) | ES6 (2015) |
| Use in modern code? | ❌ Avoid | ✅ Yes | ✅ Yes (preferred) |
Understanding Scope
Scope defines where in your code a variable is accessible.
var — Function Scope
var is accessible anywhere within the function it was declared in — even outside the block (if, for, etc.) where it appears.
function testVar() {
if (true) {
var message = "Hello from var";
}
console.log(message); // ✅ accessible outside the if block!
}
testVar();Hello from var
3
let and const — Block Scope
let and const are only accessible within the block { } they were declared in:
function testLet() {
if (true) {
let message = "Hello from let";
console.log(message); // ✅ accessible inside the block
}
// console.log(message); // ❌ ReferenceError! 'message' not defined here
}
testLet();Hello from let
Loop done, j is gone
Scope Visualization
Understanding Hoisting
JavaScript hoists declarations to the top of their scope during compilation (before any code runs). But var, let, and const hoist differently:
var hoisting:
console.log(name); // undefined — not an error! var is hoisted
var name = "Kavya";
console.log(name); // "Kavya"undefined Kavya
This happens because JavaScript internally sees it as:
var name; // hoisted to top — initialized as undefined
console.log(name); // undefined
name = "Kavya"; // assignment stays where it was written
console.log(name); // "Kavya"let and const — Temporal Dead Zone (TDZ)
console.log(score); // ❌ ReferenceError: Cannot access 'score' before initialization
let score = 95;
console.log(score);ReferenceError: Cannot access 'score' before initialization
TEMPORAL DEAD ZONE (TDZ) for let/const:
Start of block
│
│ ← TDZ begins here (declaration is "hoisted" but not usable)
│ ← accessing 'score' here throws ReferenceError
│
let score = 95; ← TDZ ends, variable is initialized
│
│ ← 'score' is accessible from here downward
│
End of blockconst — Reassignment vs Mutation
const prevents reassignment (changing what the variable points to), but it does NOT make objects or arrays immutable:
{ name: 'Arjun', age: 22, city: 'Chennai' }
[1, 2, 3, 4]Re-declaration Behavior
// var allows re-declaration (silently overwrites)
var city = "Delhi";
var city = "Mumbai"; // ✅ allowed — no error
console.log(city); // "Mumbai"
// let FORBIDS re-declaration in the same scope
let country = "India";
// let country = "Bharat"; // ❌ SyntaxError: Identifier 'country' has already been declared
// const FORBIDS re-declaration
const MAX = 100;
// const MAX = 200; // ❌ SyntaxErrorMumbai
The var Global Property Problem
// var at the top level creates a property on window (browser)
var globalVar = "I'm on window";
console.log(window.globalVar); // "I'm on window"
// let/const do NOT create window properties
let globalLet = "I'm NOT on window";
console.log(window.globalLet); // undefinedThis var behavior can accidentally overwrite built-in browser properties (like window.name, window.status) — another reason to avoid var.
Classic var Bug in Loops (and the let Fix)
var: 3 var: 3 var: 3
let: 0 let: 1 let: 2
This is one of the most famous JavaScript bugs that let was specifically designed to fix.
Common Mistakes
❌ Mistake 1: Using const and expecting objects to be immutable
// ❌ WRONG assumption
const config = { debug: false };
config.debug = true; // This WORKS — const doesn't freeze objects!
console.log(config.debug); // true// ✅ To truly freeze an object, use Object.freeze()
const config = Object.freeze({ debug: false });
config.debug = true; // Silently fails (no error in sloppy mode)
console.log(config.debug); // false — still false!❌ Mistake 2: Using var in loops with async operations
❌ Mistake 3: Declaring everything with let "just to be safe"
// ❌ NOT IDEAL — everything as let
let PI = 3.14159; // PI will never change
let MAX_SIZE = 100; // This is a constant
let appName = "WoHoTech"; // Never reassigned// ✅ BETTER — use const for non-changing values
const PI = 3.14159;
const MAX_SIZE = 100;
const appName = "WoHoTech";Using const signals intent — it tells other developers "this value should never change."
Key Takeaways
varhas function scope and is hoisted withundefined— avoid in modern codelethas block scope and is in TDZ before declaration — use for values that changeconsthas block scope, is in TDZ, and cannot be reassigned — use for everything elseconstdoes NOT make objects/arrays immutable — it only prevents reassignment- The famous
varin loop + setTimeout bug is solved by switching tolet - Modern rule:
constby default,letwhen you need reassignment, nevervar
Interview Questions & Answers
Q1. What is the main difference between var, let, and const?
Answer:
var: function-scoped, hoisted asundefined, allows re-declaration and reassignmentlet: block-scoped, in TDZ until declared, no re-declaration, allows reassignmentconst: block-scoped, in TDZ until declared, no re-declaration, no reassignment
The key practical differences: let and const are block-scoped (safer), and const signals immutable binding.
Q2. What is hoisting in JavaScript?
Answer: Hoisting is JavaScript's behavior of moving variable and function declarations to the top of their scope during the compilation phase (before execution). var declarations are hoisted AND initialized to undefined. let and const declarations are hoisted but placed in the Temporal Dead Zone — they exist but cannot be accessed until the declaration line is reached.
Q3. What is the Temporal Dead Zone (TDZ)?
Answer: The Temporal Dead Zone is the region from the start of a block to the let/const declaration line where the variable is in scope but cannot be accessed. Accessing it throws a ReferenceError: Cannot access 'variable' before initialization. This prevents the confusing var behavior of accessing a variable before its assignment (getting undefined).
Q4. Can you change the value of a const variable?
Answer: You cannot reassign a const variable (that throws TypeError). However, if the value is an object or array, you can mutate its contents — add/remove properties, push/pop elements — because const only prevents the variable from pointing to a different object, not the object's contents from changing.
Q5. Why should you avoid var in modern JavaScript?
Answer: Three main reasons:
- Function scope instead of block scope leaks variables outside
if/forblocks - Hoisting to
undefinedallows using variables before declaration without an error — hiding bugs - Allows re-declaration which can accidentally overwrite variables in the same scope
let and const fix all three of these problems.
Q6. What happens when you use var inside a for loop with setTimeout?
Answer: All the setTimeout callbacks share the same var variable (function-scoped, single binding). By the time the callbacks run, the loop has finished and i holds its final value. All callbacks print the same last value. With let, each loop iteration creates a new block-scoped binding, so each callback captures its own unique value.
Q7. What is the difference between re-declaration and reassignment?
Answer:
- Re-declaration: using the same keyword again for the same name in the same scope:
var x = 1; var x = 2;(allowed with var, error with let/const) - Reassignment: changing the value a variable holds using
=:let x = 1; x = 2;(allowed with let/var, error with const)
Q8. When should you use let vs const?
Answer: Use const for any value that won't be reassigned — which is most values in typical code (constants, objects, arrays, functions). Use let only when you specifically need to reassign the variable (like a counter in a loop, or a flag that changes). The industry convention is const by default, let when necessary. This makes code intent clearer and reduces bugs from accidental reassignment.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript var vs let vs const – Complete Guide with Scope, Hoisting & Best Practices.
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, basics, var, let
Related JavaScript Master Course Topics