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.
varas a conscious indicator that this variable is intended to be scoped to the entire function might be a useful "self-documenting" convention.letstatement right at the top of a function, I think it's just as obvious that you intended to scope it to the entire function. I don't think usingvarmakes it any clearer than simply locating it at the top.varstill exists, is backwards-compatibility. If it weren't for that, they'd have removedvaraltogether, or never introducedletin the first place, instead changing the semantics ofvarto what it arguably should have been all along.varseem thin to me, and not enough to warrant having a third kind of variable that jumps around. You can scope aletto a whole function simply by placing it at the top of the function, which is much clearer in intent than writingvarin a block (in order to have it hoisted out of that block so you can then use it outside the block - weird). He warns that if you scope aletto a function then "it's just position that signals the difference, rather than syntax", but I think that's a good thing.var. the examples he presents for keepingvarseem contrived -- and are based on severe coding errors. It's much better to run into an error and be forced to fix such errors than to use language functions that let one get away with it! What's next, advise to wrap everything in an try/catch to prevent crashes? The rest of that link is good but I don't agree at all with that particular part.