var vs let vs const
Understand the differences between var, let, and const — scope, hoisting, reassignment, and when to use each.
Side-by-Side Comparison
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Redeclaration | Allowed | Not allowed | Not allowed |
| Reassignment | Allowed | Allowed | Not allowed |
| Global object property | Yes (window.x) | No | No |
Code Examples
var
- Function-scoped (not block-scoped)
- Hoisted and initialized to undefined
- Can be redeclared in the same scope
- Can be reassigned
function example() {
console.log(x) // undefined (hoisted)
var x = 10
if (true) {
var x = 20 // same variable!
}
console.log(x) // 20
}let
- Block-scoped (respects {curly braces})
- Hoisted but NOT initialized (TDZ)
- Cannot be redeclared in the same scope
- Can be reassigned
function example() {
// console.log(x) // ReferenceError (TDZ)
let x = 10
if (true) {
let x = 20 // different variable
console.log(x) // 20
}
console.log(x) // 10
}const
- Block-scoped (like let)
- Hoisted but NOT initialized (TDZ)
- Cannot be redeclared or reassigned
- Object/array properties CAN still be mutated
const obj = { name: 'Alice' }
obj.name = 'Bob' // OK — mutating property
// obj = {} // TypeError — reassignment
const arr = [1, 2, 3]
arr.push(4) // OK — mutating array
// arr = [5, 6] // TypeError — reassignmentWhen to Use Which
const
Default choice. Use for all values that won't be reassigned — objects, arrays, functions, primitives.
let
Use when the binding needs to change — loop counters, accumulators, conditional assignments.
var
Avoid in modern code. Only appears in legacy codebases or when you specifically need function-scoping.
Common Mistakes
- Thinking const makes objects immutable — it only prevents reassignment of the binding
- Using var in for loops and expecting block scope — var leaks out of the loop body
- Not understanding TDZ — accessing let/const before declaration throws ReferenceError, not undefined
Interview Questions
What is the Temporal Dead Zone (TDZ)?
The TDZ is the period between entering a scope and the let/const declaration being reached. Accessing the variable during this period throws a ReferenceError. This exists because let/const are hoisted but not initialized.
Why does var in a for loop cause issues with closures?
Because var is function-scoped, all iterations share the same variable. By the time callbacks execute, the loop has finished and the variable holds the final value. Using let creates a new binding per iteration, fixing this.
Can you change a property of a const object?
Yes. const prevents reassignment of the binding, not mutation of the value. To make an object truly immutable, use Object.freeze() — but note it is shallow.