JavaScript ES6 – Reasons to Use the ‘var’ Keyword in ES6

es6javascript

Babel's guide to ES6 says:

let is the new var.

Apparently the only difference is that var gets scoped to the current function, while let gets scoped to the current block. There are some good examples in this answer.

I can't see any reason to use var in ES6 code. Even if you want to scope a given variable to the whole function, you can do so with let by putting the declaration at the top of the function block, which is what you should be doing with var anyway to indicate the actual scope. And if you want to scope something more finely in an for block or something, then you can do that too.

So my instinct is to stop using var altogether when writing ES6 code.

My question is, am I wrong about this? Is there any legitimate case where var would be preferable over let?

Best Answer

Doug Crockford discusses let at this point in his talk, "The Better Parts".

The point is, let avoids a source of misunderstanding, esp. for programmers with expectations set by languages with block-scope. A var has function scope (it declares a variable that's visible throughout the function) even though it looks like it has block scope.

var might possibly still be useful in an extreme case like machine-generated code, but I'm stretching hard there.

(const is also new and has block scope. After let x = {'hi': 'SE'} you can reassign to x, while after const y = x you cannot reassign to y. That's often preferrable since it keeps something from accidentally changing out from under you. But to be clear, you can still modify the object y.hi = 'SO' unless you freeze it.)

Realistically, your impression is right on for ES6: Adopt let and const. Stop using var.

(In another performance of "The Better Parts", Doug says why === was added rather than fixing the problems of ==. == produces some "surprising" results, so just adopt ===.)


A Revealing Example

Mozilla Developer Network gives an example where var does not work as intended. Their example is a realistic one that sets onclick handlers in a web page. Here's a smaller test case:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

var trips us up because all loop iterations share the same function-scoped i variable, which has the value 5 after the loop finishes.


Another Telling Example

function f(x) {
    let y = 1;
    if (x > 0) {
        let y = 2;  // `let` declares a variable in this block
    }
    return y;
}
[f(1), f(-1)]  // --> [1, 1]

// Start over, but change `let` to `var`.
// --> [2, 1]

let declares block-scoped variables. var confuses us by referring to the same variable throughout the function.

Related Topic