17

If the let keyword introduces a proper implementation of block scope, does var any longer have a use case? I am looking at this from a software design standpoint rather than a syntactical, "well you could" standpoint.

Bergi
  • 572,313
  • 128
  • 898
  • 1,281
Kamuela Franco
  • 614
  • 1
  • 5
  • 15
  • Related: http://stackoverflow.com/questions/762011/javascript-let-keyword-vs-var-keyword – Marvin Aug 05 '15 at 15:35
  • 2
    I understand the difference, I am just trying to pick programming brains right now for why `var` will not just leave common usage forever. – Kamuela Franco Aug 05 '15 at 15:41
  • Possible duplicate of [What's the difference between using "let" and "var" to declare a variable?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var-to-declare-a-variable) – James Donnelly Feb 27 '18 at 08:23

4 Answers4

17

If the let keyword introduces a proper implementation of block scope, does var any longer have a use case?

There could be one use case: let declarations in global scope don't create a property on the global object. Example:

"use strict"; // for chrome
var foo = 42;
let bar = 21;
console.log('window.foo (var)', window.foo); // 42
console.log('window.bar (let)', window.bar); // undefined

From 8.1.1.4 Global Environment Records

The object Environment Record component of a global Environment Record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the declarative Environment Record component of the global Environment Record.

However, this can also easily be solved by creating an explicit global variable using by assigning to the global object directly:

window.foo = 42;

This would also be the only way to create global classes btw, because the class declaration has the same behavior.

(Note: I'm not advocating the use of global variables)


There are syntax constructs where you can only use var, but that's more a consequence of the how the spec evolved and doesn't really serve any practical purpose. For example:

if (true)
  var foo = 42; // valid but kind of useless or bad design

// vs

if (true)
  let foo = 42; // invalid

Block scope is not the only useful feature though. The temporal dead zone is another handy feature to find bugs more easily. Compare:

var foo = 42;
function bar() {
  console.log(foo); // undefined
  var foo = 21;
}
bar();

// vs

var foo = 42; // or `let`, doesn't matter
function bar() {
  console.log(foo); // ReferenceError, temporal dead zone
  let foo = 21;
}
bar();

You get a reference error when trying to access a let variable that wasn't initialized yet.

Karel Bílek
  • 34,538
  • 28
  • 89
  • 139
Felix Kling
  • 756,363
  • 169
  • 1,062
  • 1,111
  • 2
    From what you're saying, it seems like `let` introduces a stricter environment for business logic. It's my opinion that it has to phase the use of `var` out over time in enlightened circles. – Kamuela Franco Aug 05 '15 at 18:09
  • why does the let declaration after the if statement fail without curly braces? , ie `if (true) let foo = 42; // invalid`, whereas `if (true){ let foo = 42; // valid }` – user1063287 Nov 30 '21 at 16:05
  • 1
    @user1063287: Just from a practical perspective there is no point in declaring a variable that cannot be accessed anywhere else (the `let` variable wouldn't be visible outside the `if` statement but there is no other statement in the `if` statement). From a grammar perspective, an `if` statement's body has to be a *Statement*. A `let` "statement" is a *LexicalDeclaration*, which is a *Declaration* but **not** a *Statement*. But a *BlockStatement* (`{...}`) can contain a list of *Statement*s and *Declaration*s. – Felix Kling Nov 30 '21 at 17:42
6

let can't be used in global scope yet. var can.

This is what you get from Chrome when you try a global let outside of strict mode:

Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

Amit
  • 43,881
  • 8
  • 73
  • 106
5

Practically there may be some use-cases.

1. Declare variable in try-catch like so:
try {
    //inits/checks code etc
    let id = getId(obj);

    var result = getResult(id);
} catch (e) {
    handleException(e);
}

//use `result`

With let the result declaration would be before try, - a bit early and out of context.

2. Same for conditional declarations:
if (opts.re) {
    var re = new RegExp(opts.re);
    var result = match(re);
    if (!result) return false;
}

// result is available here

With let this code would be forced to complain "good style", though that might be impractical.

3. Loop block:
for (var x = 0; x < data.width; x++) {
    if (data[x] == null) break;
    //some drawing/other code
}

//`x` pointing to the end of data

Some may consider that untidy, I myself prefer lets, but if code I already has vars - that's natural to keep using them.

dy_
  • 5,552
  • 5
  • 23
  • 30
  • Then why not declare a variable with `let` before the `try` or `if` and assign a value afterwards? In my opinion, it would make it more readable, being able to follow more easily in which block what variables are available and where they are declared within that same block. – undefined Oct 25 '21 at 15:17
1

You can use var if you want to deconstruct something into the function scope, for example a conditional:

if (Math.random() > 0.5)
  var {a,b} = {a: 1, b: 2}
else 
  var {a,b} = {a: 10, b: 20}

// Some common logic on a and b
console.log(a, b)

With let you would have to write something like

let result;

if (Math.random() > 0.5)
  result = {a: 'foo', b: 'bar'}
else 
  result = {a: 'baz', b: 'qux'}

// Using const might make more sense here
let {a, b} = result; 
// Some common logic on a and b
console.log(a,b)
Uri
  • 2,256
  • 2
  • 24
  • 24
  • with `let`, one can change the property directly without causing error like `result = {a: 'foo', b: 'bar'}; result.a= poof` – Eldwin Mar 23 '21 at 21:28
  • Why not `let a, b;` then `a = "foo"`, `b = "bar"`? Seems simpler to me and makes it obvious in which block these variables can be used. – undefined Oct 25 '21 at 15:20