问题
I’m sure it’s a little caveat somewhere but, here is the issue:
var x = x || {}; // Works!
let y = y || {}; // ReferenceError: can't access lexical declaration 'y' before initialization
const z = z || {}; // ReferenceError: can't access lexical declaration 'z' before initialization
The let
and const
cases throw “ReferenceError: can't access lexical declaration 'variableName' before initialization”.
What is going on here? I can kind of understand the const
one, but how is let
not working either?
回答1:
Variables declared with
var
are hoisted to the top of the enclosing function or global scope. They are assigned the initial value ofundefined
. Hence the example line of codevar x = x || {};
is transformed by hoisting and default value initialization into this equivalent code:var x = undefined; x = x || {};
Because
x
already has a value when the right-hand side of the assignment statement is evaluated, the code proceeds normally.Side note: You can declare a variable with
var
even after the first assignment (due to top-hoisting), and declaring more than once is idempotent (e.g.var x; var x;
).Variables declared with
let
andconst
are hoisted to the top of the enclosing block, but are not given a default value. If such a variable is read before a value is assigned, aReferenceError
is thrown. Your example line of code is transformed by hoisting into this equivalent code:let y; y = y || {};
To execute the assignment statement, the right side is first evaluated, then its value is assigned to the variable on the left side. But in this case, the right side reads
y
, which has not been assigned a value yet — hence an error is thrown.Everything that is in the same scope as the
let
statement, but executed earlier (i.e. abovelet
or the right-hand side of alet
assignment) is within the Temporal Dead Zone (TDZ).
Note that in JavaScript, a piece of code like let x = x + 1;
throws an exception only if execution reaches that statement. Whereas in other languages like Java, the same piece of code is always a compile-time error, even if it’s buried inside an if(false){...}
. This emphasizes the behavior of variable hosting, and the fact that JavaScript examines what the code means when it is executed, hence these examples are not syntax errors in a strict sense.
来源:https://stackoverflow.com/questions/42967145/why-does-a-let-assignment-that-uses-the-same-variable-name-in-its-right-hand-s