Chapters

FundamentalsChapter 10 of 21

var

The old declaration, why it behaves oddly, and why you will still meet it.

You will not write var, but you will read it. Every JavaScript file older than about 2016 uses it, so it is worth twenty minutes to recognise what it does.

Function scope, not block scope

let and const live inside the nearest braces. var ignores blocks entirely and lives in the whole function.

JavaScript

JavaScript

function check() {
  if (true) {
    var inside = 'leaked';
  }
  return inside;
}

console.log(check());

Output

leaked

The same code with let throws a ReferenceError, which is the more useful answer.

Hoisting

A var declaration is moved to the top of its function before anything runs. The assignment stays where it was, so the name exists early holding undefined.

JavaScript

JavaScript

function show() {
  console.log(value);
  var value = 'set later';
  console.log(value);
}

show();

Output

undefined
set later

No error, just undefined, which is exactly the kind of bug that survives to production. let makes the same code throw.

The classic loop bug

Because there is one var for the whole function rather than one per pass, everything that captures it ends up sharing the final value.

JavaScript

JavaScript

var jobs = [];

for (var i = 0; i < 3; i++) {
  jobs.push(function () { return i; });
}

console.log(jobs.map(function (job) { return job(); }));

Output

[3, 3, 3]

All three functions read the same i, and by the time they run the loop has finished and left it at 3. Change var to let and the answer becomes [0, 1, 2].

Redeclaration is allowed

Declaring the same var twice is legal and silent, so two unrelated pieces of code can share a name by accident.

JavaScript

JavaScript

var total = 1;
var total = 2;

console.log(total);

Output

2

Note

Recognise it, do not reach for it. There is no case where var is the better choice in new code.

Test yourself

2 questions

What does hoisting do to a var declaration?

Show the answer

Moves the declaration to the top of the function, leaving the assignment in place Which is why the name exists early holding undefined instead of throwing.

Why does a var loop counter give [3, 3, 3]?

Show the answer

There is one counter for the whole function, shared by every function made in the loop let creates a fresh binding each pass, which is the whole point of the change.

Next chapter

Operators

The symbols that combine values, and the order they apply in.