Skip to content
JavaScript

var vs let vs const in JavaScript (Scope and Hoisting)

By The EbookWale Team · Updated June 16, 2026 · 3 min read

Use const by default, let when you need to reassign, and avoid var. Here's the real difference between var, let and const in JavaScript — block vs function scope, hoisting, and the temporal dead zone.

In modern JavaScript the rule is simple: use const by default, let when you need to reassign, and avoid var. const and let are block-scoped and predictable; var is function-scoped and hoisted in ways that cause classic bugs. Understanding why is a staple interview question and the key to avoiding a whole category of mistakes.

The quick rule

const name = "Ana";     // won't be reassigned → const
let count = 0;          // will change → let
count += 1;
// var ...               // legacy — don't reach for it

Start everything as const. If you later find you need to reassign it, change it to let. You’ll be surprised how rarely you need let.

Block scope vs function scope

This is the core difference. let and const are block-scoped — they exist only inside the nearest { }. var is function-scoped — it ignores blocks and exists throughout the whole function.

if (true) {
  var a = 1;
  let b = 2;
}
console.log(a);   // 1 — var leaked out of the block
console.log(b);   // ReferenceError — let stayed in the block

var leaking out of if blocks and loops is a frequent source of bugs. Block scoping keeps variables where you expect them.

function scope { block } let b ✓ var a var leaks out! stays in block
let/const are block-scoped; var leaks to the whole function.

The classic loop bug

The most famous demonstration — and a guaranteed interview question — combines scope with closures:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// logs 3, 3, 3 — one shared `i`

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// logs 0, 1, 2 — a fresh `i` per iteration

var creates one shared i; let creates a new binding each iteration. This single example is why let exists.

Hoisting and the temporal dead zone

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

  • var is hoisted and initialised as undefined — using it before its line gives undefined (silent, surprising).
  • let/const are hoisted but not initialised — using them before their line throws a ReferenceError. The gap between the top of the scope and the declaration is the temporal dead zone (TDZ).
console.log(x);   // undefined (var hoisted)
var x = 5;

console.log(y);   // ReferenceError (TDZ)
let y = 5;

The TDZ is a feature — it turns “used too early” from a silent bug into a loud error.

🔑 REMEMBER — const by default, let when reassigning, never var. const/let are block-scoped and TDZ-protected; var is function-scoped and hoists to undefined. This single habit prevents a whole class of scope bugs.

A note on const and objects

const prevents reassignment, not mutation. You can’t point a const at a new value, but you can change an object’s contents:

const user = { name: "Ana" };
user.name = "Ben";     // fine — mutating the object
user = {};             // TypeError — reassigning the binding

For truly immutable objects you’d need Object.freeze, but for everyday code, const simply means “this name won’t be reassigned.”

Where this fits

var vs let vs const is Phase 1 of the JavaScript roadmap, and it connects directly to closures (the loop bug) and scope generally.

Scope, hoisting, and the TDZ are drawn out with diagrams in JavaScript in One Month and the job-ready JavaScript in Three Months; for how the engine implements scope and bindings under the hood, JavaScript for Staff Engineers goes deeper.

Default to const, reach for let only when you must, and leave var in the past.

Frequently asked questions

What is the difference between var, let, and const?

const declares a constant that cannot be reassigned; let declares a variable you can reassign; both are block-scoped. var is the old way — it is function-scoped and hoisted, which causes surprising bugs. The modern rule is: use const by default, let when you must reassign, and avoid var.

Should I use let or const?

Default to const for everything, and switch to let only when you actually need to reassign the variable. Using const by default signals intent (this won't change), prevents accidental reassignment, and makes code easier to reason about. It does not make objects immutable — you can still mutate a const object's properties.

What is the difference between block scope and function scope?

Block scope means a variable exists only within the nearest curly braces — an if block, a loop, a function. Function scope means a variable exists throughout the entire function regardless of blocks. let and const are block-scoped; var is function-scoped, which is why var leaks out of loops and if statements.

What is hoisting in JavaScript?

Hoisting is JavaScript moving declarations to the top of their scope before running code. var declarations are hoisted and initialised as undefined, so using them early gives undefined. let and const are hoisted but not initialised, so using them before their declaration throws an error — the temporal dead zone.