Why var Leaks Out of Blocks

Grade 9, page 5 of 11. A one-minute read.

Remember Grandpa's old box, var, from Grade 1? We said it had some quirks related to scope. Here's the biggest one: var ignores block scope. It only respects function scope. So a var created inside an if block or a loop leaks out into the surrounding function (or the global scope):

JavaScript
if (true) {
  var leaky = "I escaped!";
  let polite = "I stay inside.";
}

console.log(leaky);
console.log(typeof polite);

It prints

I escaped!
undefined
JavaScript
for (var j = 0; j < 3; j++) {
  // ...
}

console.log(`After the loop, j is ${j}`);

It prints

After the loop, j is 3

The loop is over, but j is still hanging around like a guest who won't leave the party. This leaking caused countless bugs over the years, and it's the main reason let and const were invented.

Professor’s CornerThe most famous var bug

Here's a classic that caught out JavaScript developers for years. It uses setTimeout, which runs a function later, after a delay. (You'll learn all about it in College.)

JavaScript
for (var i = 1; i <= 3; i++) {
  setTimeout(() => console.log(`var: ${i}`), 10);
}

for (let k = 1; k <= 3; k++) {
  setTimeout(() => console.log(`let: ${k}`), 20);
}

It prints

var: 4
var: 4
var: 4
let: 1
let: 2
let: 3

With var, there's only one i for the entire loop. By the time the delayed functions run, the loop has finished and i is 4, so they all print 4. With let, each trip around the loop gets its own fresh k, so each function remembers its own value. Just one more reason to always use let and const!

Reading is step one

CurlyScript turns these notes into a game: short questions, an explanation after every answer, and a test at the end of each grade. Free, with nothing to sign up for.

Start learning