I was going through the Difference between var
and let
documentation example and was testing that when an undeclared variable is invoked, the globa
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 your let
variable instead of the global value. As others mentioned, this leads to the temporal deadzone issue with hoisting.
The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated
- Source (ECMAScript 8th edition)
This code shows where placing code causes the TDZ:
// Accessing `x` here before control flow evaluates the `let x` statement
// would throw a ReferenceError due to TDZ.
// console.log(x);
let x = 42;
// From here on, accessing `x` is perfectly fine!
console.log(x);
You can see that wrapping the let
inside its own block block fixes it:
x=3;
{
let x = 42;
console.log(x); // 42
}
Alternatively, you can define the global explicitly on the window
object:
window.x=3;
let x = 42;
console.log(x); // 42
Did you have a look at the let
docs at MDN? They describe a temporal dead zone and errors with let.
ES6 does hoist a let
variable to the top of its scope. Differently to var
variable, when using let
you must not access the variable before it is declared. Doing so fail with a ReferenceError
(a.k.a. let's temporal dead zone).
As Konstantin A. Magg explained, that's because let
variables are hoisted and attempts to reference them before initialization throw (temporal dead zone).
If you don't want this, you can split the code into different scripts:
<script>
x = 3;
console.log(x); // 3
</script>
<script>
let x = 42;
console.log(x); // 42
</script>
Note x = 3
will throw in strict mode.