Quick Summary
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Reassignment | Yes | Yes | No |
| Redeclaration | Yes | No | No |
var - The Old Way
var was the original way to declare variables in JavaScript.
var name = 'John';
var name = 'Jane'; // No error - redeclaration allowed
name = 'Bob'; // Reassignment allowed
Problems with var
1. Function Scope (not Block Scope)
if (true) {
var x = 10;
}
console.log(x); // 10 - var "leaks" out of blocks
2. Hoisting Issues
console.log(y); // undefined (not an error!)
var y = 5;
3. Loop Variable Leaking
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Outputs: 3, 3, 3 (not 0, 1, 2!)
let - Block Scoped Variable
let was introduced in ES6 (2015) to fix var's problems.
let age = 30;
// let age = 25; // Error: Cannot redeclare
age = 25; // OK: Can reassign
Benefits of let
1. Block Scope
if (true) {
let x = 10;
}
// console.log(x); // Error: x is not defined
2. No Hoisting Issues
// console.log(z); // Error: Cannot access before initialization
let z = 5;
3. Works Correctly in Loops
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Outputs: 0, 1, 2 (correct!)
const - Constant Reference
const creates a constant reference to a value.
const PI = 3.14159;
// PI = 3.14; // Error: Cannot reassign
const user = { name: 'John' };
user.name = 'Jane'; // OK: Can modify properties
// user = {}; // Error: Cannot reassign reference
Important: const ≠ Immutable
const arr = [1, 2, 3];
arr.push(4); // OK: [1, 2, 3, 4]
arr[0] = 99; // OK: [99, 2, 3, 4]
// arr = [5, 6, 7]; // Error: Cannot reassign
For truly immutable objects, use Object.freeze().
Best Practices
- Default to const - Use const for all variables that won't be reassigned
- Use let when needed - Only use let if the variable will be reassigned
- Avoid var - There's no good reason to use var in modern JavaScript
// Good practice
const API_URL = 'https://api.example.com';
const users = [];
let count = 0;
count++;
// Bad practice
var globalVar = 'avoid this';
Temporal Dead Zone (TDZ)
Both let and const have a "temporal dead zone" - the period between entering a scope and the variable being declared.
{
// TDZ starts
// console.log(x); // Error!
let x = 10; // TDZ ends
console.log(x); // 10
}
Conclusion
- Use const by default
- Use let only when you need to reassign
- Never use var in new code