I was going through the Difference between var
and let
documentation example and was testing that when an undeclared variable is invoked, the global scope automatically provides a declaration for it (that's why the following snippet does not throw an error in any of the variables):
x = 3;
console.log(x);
(function() {
y=x+39;
})()
console.log(y);
However, when one variable is declared with let
after the assignment in the same global scope:
x=3;
let x = 42;
console.log(x);
One of the following errors is thrown:
ReferenceError:
x
is not defined (Chromium)ReferenceError: can't access lexical declaration
x
before initialization (Firefox)
I understand that let
does not allow x
to hoist, but since it was previously referenced (implying an automatic declaration from the global scope) shouldn't in this case a re-declaration happen?
SyntaxError: Identifier
x
has already been declared
And therefore the error above thrown?
I also understand that in strict mode the first snippet would throw a ReferenceError, so does this mean that let
forces this particular rule of strict mode (all variables need to be declared) upon the global scope?
You're right, it's weird behavior. The reason it's giving those errors is because it thinks you're trying to assign the value
3
to yourlet
variable instead of the global value. As others mentioned, this leads to the temporal deadzone issue with hoisting.- Source (ECMAScript 8th edition)
This code shows where placing code causes the TDZ:
You can see that wrapping the
let
inside its own block block fixes it:Alternatively, you can define the global explicitly on the
window
object: