Home/Learn/JavaScript & TypeScript/Scope & Hoisting — let, const, var and the TDZ

Scope & Hoisting — let, const, var and the TDZ

Beginner
Language Core

var is function-scoped and hoisted as undefined; let and const are block-scoped and hoisted into a temporal dead zone that throws if you touch them early. Use const by default, let when you must reassign, var never.

Overview

Scope determines where a name is visible. JavaScript has three kinds — global, function, and block — and which one applies depends on how you declared the variable. Before 2015 there was only var, which is function-scoped: a variable declared inside an if block leaks to the whole function. let and const introduced block scoping, matching what Java and Python programmers expect. All declarations are hoisted, meaning the engine knows about them before the line runs; the difference is that var is initialised to undefined while let and const are not initialised at all, leaving a "temporal dead zone" where reading them throws.

Block Scope vs Function Scope

This is the difference that causes real bugs, most famously in loops. var has one binding for the whole function; let creates a fresh binding per iteration.

The loop bug that made let necessary
// var — one binding, shared by every callback
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}
// 3, 3, 3  — the loop finished before any callback ran

// let — a new binding each iteration
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}
// 0, 1, 2

// var also leaks out of blocks:
if (true) { var leaked = 'yes'; let contained = 'no' }
console.log(leaked)     // 'yes'
console.log(contained)  // ReferenceError

The Temporal Dead Zone

let and const are hoisted, but reading them before the declaration throws rather than giving undefined. That is deliberate: it turns a silent bug into a loud one.

Hoisting, and what the TDZ protects you from
console.log(a)   // undefined — var is initialised to undefined
var a = 1

console.log(b)   // ReferenceError: Cannot access 'b' before initialization
let b = 1
// ^ b exists from the top of the block but is in the TDZ until this line

// Function declarations are fully hoisted — callable before defined:
greet()                      // works
function greet() { ... }

// Function expressions are not:
greet2()                     // TypeError: greet2 is not a function
var greet2 = function () {}  // var is undefined at call time

const Does Not Mean Immutable

const prevents reassignment of the binding, not mutation of the value. This trips up people who read it as Java's final on a collection, which has the same limitation.

const binds the name, not the contents
const user = { name: 'Asha' }
user.name = 'Ravi'      // fine — mutating the object
user = {}               // TypeError — reassigning the binding

const list = [1, 2]
list.push(3)            // fine
list = []               // TypeError

// To actually freeze (shallow):
const frozen = Object.freeze({ a: 1 })
frozen.a = 2            // silently ignored (throws in strict mode)

// Default to const; reach for let only when you reassign:
const total = items.reduce((sum, i) => sum + i.price, 0)

Key Points to Remember

  • 1var is function-scoped and leaks out of blocks; let and const are block-scoped
  • 2All declarations hoist, but var initialises to undefined while let/const sit in a temporal dead zone that throws
  • 3let creates a fresh binding per loop iteration — this is why closures in loops work with let and not var
  • 4const prevents reassignment, not mutation: const objects and arrays can still be changed
  • 5Default to const, use let when reassigning, and treat var as legacy

Interview Questions

Sign in to ask Aria
1

What is the difference between var, let and const?

Easy
2

Why does a for loop with var print 3,3,3 to setTimeout but let prints 0,1,2?

Medium
3

What is the temporal dead zone, and why was it introduced rather than defaulting to undefined?

Medium

Ask Aria about Scope & Hoisting — let, const, var and the TDZ

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…