var vs let vs const
The Three Declarations, Fully Decoded
LinkedIn Hook
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i), 100);prints3, 3, 3. Changevartoletand it prints0, 1, 2.If you can explain WHY in one sentence, you understand scope. If you can't, this lesson is for you.
var is function-scoped. let and const are block-scoped. var attaches to
window. let and const don't. const prevents reassignment of the binding — NOT mutation of the object it points to. All three are hoisted, but only var is auto-initialized toundefined.In this lesson you'll get the full comparison table, the classic setTimeout trap, the
const user.name = ...gotcha, and exactly whyvarin the global scope can silently overwrite third-party library globals.If you're still writing
varin 2026, you'll stop after reading this.Read the full lesson -> [link]
#JavaScript #InterviewPrep #VarLetConst #Scope #JSFundamentals #Frontend #CodingInterview
What You'll Learn
- Full scope / hoisting / re-assignment / re-declaration comparison
- Why
varleaks out ofifandforblocks butletdoesn't - Why
for (var i ...)withsetTimeoutprints the same number three times - What
constactually freezes (hint: the binding, not the value) - Why global
varpollutes thewindowobject
The Full Comparison
This is one of the most asked interview topics. Here's the complete comparison.
Quick Comparison Table
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function scope | Block scope | Block scope |
| Hoisted? | Yes -> undefined | Yes -> TDZ | Yes -> TDZ |
| Re-declaration | Allowed | Error | Error |
| Re-assignment | Allowed | Allowed | Error |
Global window property? | Yes | No | No |
Scope Difference — The Key Distinction
// var -> function-scoped (ignores blocks like if/for)
function example() {
if (true) {
var x = 10;
}
console.log(x); // 10 — var leaked out of the if block!
}
// let -> block-scoped (respects all {} blocks)
function example2() {
if (true) {
let y = 20;
}
console.log(y); // ReferenceError: y is not defined
}
The Classic for Loop Problem
// var: all callbacks share the SAME variable
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Output: 3, 3, 3 (NOT 0, 1, 2!)
// let: each iteration gets its OWN copy
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Output: 0, 1, 2
Why does var print 3, 3, 3? Because var i is function-scoped — there's only ONE i variable. By the time the setTimeout callbacks run, the loop has finished and i is already 3.
Why does let work? Because let i creates a new i for each loop iteration. Each setTimeout callback captures its own copy.
const with Objects & Arrays
const user = { name: "Rakibul" };
// This works — you're modifying the object, not the binding
user.name = "Hassan";
user.age = 25;
// This fails — you're trying to reassign the binding
user = { name: "Someone else" }; // TypeError: Assignment to constant variable
// Same with arrays
const arr = [1, 2, 3];
arr.push(4); // Works
arr[0] = 99; // Works
arr = [5, 6, 7]; // TypeError
const freezes the binding (the reference), not the value. If you want true immutability, use Object.freeze().
var Leaks to window
var globalVar = "I'm on window";
let globalLet = "I'm NOT on window";
console.log(window.globalVar); // "I'm on window"
console.log(window.globalLet); // undefined
This is why var at the global level can accidentally overwrite browser APIs or third-party library globals.
Common Mistakes
- Treating
constas "immutable" — it only prevents re-assignment of the binding; the object it points to can still be mutated. UseObject.freeze()for shallow immutability. - Using
varinside a loop and expecting each iteration to capture its own value — it won't; all async callbacks share the one function-scopedvar. - Declaring
varat the top of a script and wondering why a library's global got overwritten —varat the top level becomes a property of thewindowobject.
Interview Questions
Q: What's the difference between var, let, and const?
varis function-scoped, hoisted asundefined, can be re-declared and re-assigned, and attaches towindowat the top level.letis block-scoped, hoisted into the TDZ, can be re-assigned but not re-declared, and does not attach towindow.constis block-scoped, hoisted into the TDZ, and cannot be re-assigned or re-declared — but mutation of the object it references is allowed.
Q: Why does the for loop with var and setTimeout print the same number?
var iis function-scoped — there is only oneifor the whole loop. All three callbacks close over the same binding. By the time the setTimeout callbacks fire, the loop has completed andiis3.let icreates a new per-iteration binding, so each callback captures its owni.
Q: Can you modify a const object's properties?
Yes.
constprevents reassignment of the binding (the variable itself), not mutation of the value. Since objects and arrays are reference types, you can modify their properties/elements. UseObject.freeze()for shallow immutability.
Q: What happens if you declare a var variable in the global scope?
It becomes a property of the global object (
windowin browsers,globalin Node). This can accidentally overwrite built-in APIs or third-party globals.letandconstdeclared globally do NOT attach towindow, which is safer.
Q: Explain var vs let vs const in one sentence each.
var: function-scoped, hoisted toundefined, attaches to window.let: block-scoped, hoisted into TDZ, re-assignable.const: block-scoped, hoisted into TDZ, binding is locked (but value can still mutate).
Quick Reference — Cheat Sheet
var vs let vs const
var let const
Scope function block block
Hoisting undefined TDZ TDZ
Re-declare yes no no
Re-assign yes yes no
Adds to window yes no no
Rule of thumb:
- Reach for const by default
- let only when you truly need to reassign
- var: don't, in modern code
Previous: Temporal Dead Zone Next: Memory Heap & Garbage Collection
This is Lesson 1.5 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.