JavaScript var, let, and const Explained: Scope, Hoisting & Best Practices

everything you need to know about var, let, and const in JavaScript, including scope, hoisting, TDZ, mutability, re-declaration, use cases, and common pitfalls.


1. Scope

var – Function Scope

  • Available throughout the entire function in which it is declared.
  • Doesn't respect block-level scope (like if, for, etc.)
js
1function example() { 2 if (true) { 3 var x = 10; 4 } 5 console.log(x); // 10 6}

let & const – Block Scope

  • Only available within the block {} where they are defined.
js
1function example() { 2 if (true) { 3 let y = 20; 4 const z = 30; 5 } 6 console.log(y); // ❌ ReferenceError 7 console.log(z); // ❌ ReferenceError 8}

2. Hoisting

All three are hoisted (moved to the top of their scope), but behave differently:

KeywordHoistedInitializedAccess Before Declaration
varYesas undefinedAllowed (undefined)
letYes❌ No❌ Throws ReferenceError
constYes❌ No❌ Throws ReferenceError

Temporal Dead Zone (TDZ)

let and const are in a "dead zone" from the start of the scope to where they are declared. You cannot access them before declaration.

js
1console.log(a); // undefined 2var a = 10; 3 4console.log(b); // ❌ ReferenceError 5let b = 20;

3. Re-declaration and Reassignment

KeywordRe-declaration (same scope)ReassignmentNotes
varAllowedAllowedMay lead to bugs
let❌ Not allowedAllowedSafer
const❌ Not allowed❌ Not allowedConstant reference
js
1var x = 1; 2var x = 2; // OK 3 4let y = 1; 5// let y = 2; // ❌ SyntaxError 6 7const z = 1; 8// z = 2; // ❌ TypeError

4. Mutability

  • const does not make the value immutable, only the binding is constant.
  • If const refers to an object or array, you can mutate its content.
js
1const arr = [1, 2]; 2arr.push(3); // Allowed 3// arr = [1, 2, 3]; // ❌ Not allowed 4 5const obj = { name: 'Balaji' }; 6obj.name = 'Boss'; // Allowed

5. Global Object Binding

  • Variables declared with var in the global scope become a property of the global object (window in browsers).
  • let and const do not attach to the global object.
js
1var a = 1; 2let b = 2; 3 4console.log(window.a); // 1 5console.log(window.b); // ❌ undefined

6. Use Cases / Best Practices

Use CasePreferred Keyword
Value changes over timelet
Constant values or referencesconst
Avoid unless legacy supportvar

Use const by default.
🔄 Switch to let only when you need to reassign.
❌ Avoid var in modern code.


7. Interview Pitfalls & Trick Questions

❓ What will this print?

js
1for (var i = 0; i < 3; i++) { 2 setTimeout(() => console.log(i), 1000); 3} 4// ❌ 3, 3, 3

🔸 var is function-scoped. By the time the setTimeout runs, the loop is over, and i is 3.

Fix with let:

js
1for (let i = 0; i < 3; i++) { 2 setTimeout(() => console.log(i), 1000); 3} 4// 0, 1, 2

8. Summary Table

Featurevarletconst
ScopeFunctionBlockBlock
HoistingYes (initialized)Yes (TDZ)Yes (TDZ)
Use before declarationAllowed (undefined)❌ ReferenceError❌ ReferenceError
RedeclarationYes❌ No❌ No
ReassignmentYesYes❌ No
Mutable contentYesYesYes (objects/arrays)
Global object bindingYes❌ No❌ No