What is the difference between var, let, and const?
All three declare variables, but differ in scope, reassignment, and hoisting.
var — function-scoped, hoisted as undefined, can be redeclared and reassigned. Avoided in modern code.
let — block-scoped, can be reassigned but not redeclared in the same scope.
const — block-scoped and assigned once; it can't be reassigned.
Rule of thumb: default to const, use let only when you must reassign, and avoid var. const freezes the binding, not the value — an object's contents can still change.
// var - function scoped, hoisted
console.log(x); // undefined (hoisted, initialized as undefined)
var x = 10;
// let - block scoped, TDZ
// console.log(y); // ReferenceError! (temporal dead zone)
let y = 20;
// const - block scoped, cannot reassign
const z = 30;
// z = 40; // TypeError: Assignment to constant variable
// const with objects (mutable content!)
const user = { name: 'John' };
user.name = 'Jane'; // OK! Object content is mutable
// user = {}; // TypeError! Cannot reassign the binding
// Block scope difference
if (true) {
var a = 1; // Leaks out of block
let b = 2; // Stays in block
const c = 3; // Stays in block
}
console.log(a); // 1
// console.log(b); // ReferenceError
// console.log(c); // ReferenceError
// Loop gotcha
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 3, 3, 3 (var is shared)
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100); // 0, 1, 2 (let creates new binding)var is hoisted and accessible before declaration (undefined). let/const are in the TDZ until declaration. var leaks out of blocks, let/const stay. The loop gotcha: var i is one shared variable (all closures see final value 3). let j creates a new binding per iteration (each closure captures its own value).
The for loop with setTimeout is the #1 var vs let interview question. Know three differences: scope (function vs block), hoisting (undefined vs TDZ), and redeclaration. const does not make objects immutable — only the binding.