Have you read the linked article about typeof? Normally, it's safe to do typeof possiblyUndeclaredVariable, but if later in the function you do let possiblyUndeclaredVariable it starts the scope defined as "uninitialized", which causes typeof to throw.
What you have to keep in mind is that JavaScript is not "a properly scoped language". Pretending that it is will cause you to miss key aspects of how the tool works. This helps no one, including you. Please, for as crappy as the language might feel, approach the language on its own terms.
Function scopes and variable hoisting was not the best parts of JS anyway. let brings lexical scope into the game, which I think is a great progress. And you cannot expect a variable to be defined outside of its lexical scope. That's not any different that trying to access a variable outside of a function that is defined in.
If people were abusing variable hoisting in some way, they can continue to do so, by not using `let`.
If I'm following the blog post correctly, let does have effects outside of its lexical scope: it effectively makes the variable even more undefined than a totally non-existent variable. That is, the following code will not throw anything:
// x has not been defined or initialized anywhere
console.log(typeof x)
However, if you add a let statement after it like so:
// x has not been defined or initialized here
console.log(typeof x)
let x = "foo";
typeof will fail with an exception, because the let statement changes x from an undefined variable to a new state that isn't even undefined anymore.
It's not having an effect outside of its lexical scope. You introduce the let into the same lexical scope as the console.log.
It will also throw an exception every single time. So unless you're adding a variable, and then never testing the code path that hits the new line, you're probably going to catch it pretty early.
I understand, but I believe this still happens only within the lexical scope where the variable has been defined with let.
TBH, It doesn't bother me at all. I think I can even go ahead and say the latter makes much more sense. Using the former one is abusing the weaknesses of the language that has come along with it throughout its history.
We have been whining about the bad parts of JavaScript for a long, long time and I think these changes are for the better for all of us.
> And you cannot expect a variable to be defined outside of its lexical scope.
Okay, but since `typeof x` can return "undefined", I would expect it to return `undefined` if x is no defined. Now, sometimes `typeof x` returns `undefined` if x is not defined, but other times it raises if x is no defined. That's the issue.
I too predict this is going to give people a lot of trouble. We will see.
And the worst thing is, introducing a let variable affects code outside of the implicit lexical scope created by that let. The switch from "undefined" to "more undefined" happens one scope above. Even if it doesn't create much of a trouble for people, it feels like a very ugly design.
That part of the article isn't particularly clear. The intended behavior of let is great. The unintended behavior - that it can cause typeof to fail - is bad.
I guess the argument here is that let adds inconsistency? ie: var statements are hoisted and let statements aren't. It's a double edged sword: On the wone hand it can be used to improve readability, but it also adds complexity/more to bear in mind.
If I'm not mistaken that's not hoisting, since that code will work as long as a() is called after b is declared regardless of the hoisting. Keep in mind b is only accessed when a() is actually executed, not when it's declared!
Hoisting works like this:
a();
function a() {
console.log("FOO");
}
Which might or might not be more readable, depending on your tastes.