Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would let statement behave so much different from var?

I know let is to declare block scope local variables, but why doesn't it support redeclaration and hoisting like var does?

What's the design purpose of this limitation?

(function(){
    'use strict';
    alert(a);       // undefined
    var a;
})();

(function(){
    'use strict';
    alert(a);       // error
    let a;
})();

(function(){
    'use strict';
    var a;
    var a;
    alert(a);       // undefined
})();

(function(){
    'use strict';
    let a;
    let a;          // error
    alert(a);
})();
like image 215
Rufus Avatar asked Oct 21 '15 07:10

Rufus


Video Answer


2 Answers

The idea is to create a tool that's more unambiguous and more strict than the original var.

As a human, the following is valid JavaScript but nearly impossible to understand:

alert(a); // Where does a come from? Why does this not throw?
/* 1000 lines later, or even in an entirely different file */
var a;

Moreover, imagine code with 5 var declarations for the same variable on the same scope, some in if statements, some in fors. Which is the first? What value will end up being created?

The idea was to fix some of the bad parts of var.

like image 72
Madara's Ghost Avatar answered Sep 24 '22 07:09

Madara's Ghost


The same reason why any strict operator appears in any programming language - to limit the number of ways you can shoot yourself in the foot. Old-school Javascript is just chock full of those.

Note that you can use let for a block-local scope:

while (i < 5)
{
  let a = 42;

  i++;
}

Even though the loop runs a couple of times, a is always initialized properly.

Now, what would happen if you have another variable in the higher scope?

let a = 42;

while (i < 5)
{
  let a = 10;

  // What is the value of a here?
  i++;
}

// And here?

There's a certain level of ambiguity here - and ambiguity is a bad feature in a programming language. This isn't a problem with the non-block-scoped var - that one has tons of its own issues, and people misuse it all the time, but at least its obvious that var is never block-scoped. And even then - people do use it as if it were block-scoped.

The only way to fix this insanity is to make the language a bit stricter. Did this actually mean you lost any feature whatsoever? No. Variable shadowing was a bad idea with var, and it would still be a bad idea with let (and as my example shows, possibly worse).

This isn't unique to Javascript, not by a long shot. For example, in C#:

int i = 0;

int i = 42; // Compiler error: A local variable named 'i' is already defined in this scope

Why? Because you've obviously made a mistake. Perhaps you copied a piece of code from somewhere else, and didn't notice you already have another variable named i declared. Perhaps you forgot you're in the middle of another loop, that also uses i as a loop variable. There's no real legitimate use, and yet there's tons of failure modes - that's simply a terrible language feature. The simple compiler error prevents almost all of those failures from happening - and many of those failures can be very hard to find, especially if the "inner" block isn't used too often.

like image 33
Luaan Avatar answered Sep 26 '22 07:09

Luaan