JavaScript by Example

Variables

Three ways to declare variables in JavaScript - var, let, and const - each with different scoping and hoisting rules.

JavaScript has three variable declaration keywords: var, let, and const. They differ in scope, hoisting, and reassignability. Modern code uses const and let exclusively.

const declares a block-scoped binding that cannot be reassigned. It is the right choice for most declarations - it signals that the value won't change, which makes code easier to reason about.

const name = "Ada";
name = "Grace"; // TypeError: Assignment to constant variable.

let is block-scoped and allows reassignment. Use it only when a variable genuinely needs to change - a loop counter, an accumulator, a flag that flips once.

let count = 0;
count = count + 1;
console.log(count); // 1
 
for (let i = 0; i < 3; i++) {
  console.log(i); // 0, 1, 2
}
// i is not accessible here

var is function-scoped and hoisted to the top of its function. A var declared inside an if block leaks into the surrounding function - a frequent source of bugs in older code.

function demo() {
  if (true) {
    var x = 1; // hoisted to function scope
  }
  console.log(x); // 1 - leaks out of the if block
 
  let y = 2;
  // y stays block-scoped - won't leak
}

In production

The modern convention is const by default, let only when reassignment is genuinely required, and var never. ESLint's prefer-const and no-var rules enforce this automatically. Teams that skip these rules accumulate subtle bugs in async code: a var in a loop body captured by a closure resolves to the final loop value, not the value at the iteration where the closure was created - a class of bug that let eliminates entirely.

Enjoyed this? Get more essays on software craft delivered to your inbox.

Subscribe free