Why does a `let` assignment that uses the same variable name in its right-hand side throw a ReferenceError? [duplicate]

青春壹個敷衍的年華 提交于 2020-08-11 19:46:51

问题


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:


  1. Variables declared with var are hoisted to the top of the enclosing function or global scope. They are assigned the initial value of undefined. Hence the example line of code var 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;).

  2. Variables declared with let and const 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, a ReferenceError 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. above let or the right-hand side of a let 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!