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);
})();
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 for
s. Which is the first? What value will end up being created?
The idea was to fix some of the bad parts of var
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With