This is the keyword JavaScript lived with for almost twenty years. Every line written before 2015 contains it, and all of it still runs: no version of the language ever removed it, and none ever will.
Nobody writes it in new code anymore, though. Understanding why teaches more about how JavaScript handles variables than any tour of its replacements.
Definition
var declares a variable. What sets it apart from let and const is not what it can hold, but two rules inherited from the first versions of the language: it exists throughout the function containing it, and it is created before its declaration line ever runs.
var currency = "EUR";
var currency = "USD"; // no error: redeclaring is allowed
console.log(currency); // "USD"That tolerance is the first symptom. Declaring the same name twice in one file is almost always an oversight, and var lets it through without a word.
Function scope, never block scope
The scope of a variable is the region of code where its name can be used. With var, that region is the entire function, wherever the declaration happens to sit. The braces of an if or a for do not stop it.
function total() {
var sum = 0;
for (var i = 0; i < 3; i++) {
sum += i;
}
return sum + i; // i is still alive here, and holds 3
}
console.log(total()); // 6The counter was declared in the loop header and outlives it. Written with let, the last line would raise an error, since the name disappears with the closing brace.
The variable exists before its own line
Before running a function, the engine spots every var declaration inside it and creates the matching variables with the value undefined. Only the assignment stays where it was written.
console.log(price); // undefined, not an error
var price = 19;
console.log(price); // 19This mechanism, called hoisting, explains a large share of the silent bugs in older JavaScript: a typo in a name raises nothing at all, it produces an empty value that surfaces much further away.
A function declaration is hoisted too, but completely, body included. A function declared at the bottom of a file can therefore be called at the top, while a function stored in a var holds undefined until the assignment has run.
Frequently asked questions
Is var deprecated?
Not officially: no version of ECMAScript ever marked it obsolete, and removing it would break an enormous share of the existing web. In practice, modern style guides ban it from new code, and the no-var rule in ESLint exists precisely to flag it.
What happens if I forget the keyword?
Outside strict mode, assigning to a name that was never declared creates a global variable, visible from the whole program. That is a source of collisions whose culprit usually sits in another file. In strict mode, which every ES module turns on automatically, the same line raises a reference error.
Why does my loop counter hold the same value everywhere?
Because with var there is a single counter for the whole loop, shared by every function created inside it. They all read its final value at the moment they are called, never the value of the turn that created them. Swapping var for let in the header is enough to get 0, 1 and 2.
var fns = [];
for (var i = 0; i < 3; i++) fns.push(() => i);
console.log(fns[0](), fns[1](), fns[2]()); // 3 3 3