用let未正确初始化的变量出错

Mus*_*cho 2 javascript ecmascript-6

我对JS中的Set类型感到困惑。如果使用未正确初始化的Set创建变量,则不能再使用它(作为Set或原始类型)。在控制台中尝试:

let someSet = new Set(4);
/* Uncaught TypeError: number 4 is not iterable (cannot read property Symbol(Symbol.iterator))
    at new Set (<anonymous>)*/

someSet
// Uncaught ReferenceError: someSet is not defined 

let someSet = new Set([4])
// Uncaught SyntaxError: Identifier 'someSet' has already been declared
someSet
// Uncaught ReferenceError: someSet is not defined

let someSet = 'ho-ho-ho'
// Uncaught SyntaxError: Identifier 'someSet' has already been declared

someSet = 'ho-ho-ho'
// Uncaught ReferenceError: someSet is not defined

Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么吗?见屏幕:

在此处输入图片说明

T.J*_*der 8

这几乎是只能在控制台上发生的事情,因为在实际代码中,如果new Set部分let someSet = new Set(4);失败,则错误会使您脱离原来的范围,let someSet因此不会出现此问题。

诸如浏览器之类的交互式控制台必须玩具有一定范围的游戏。您最终得到了一个已声明但尚未初始化的变量(可供使用);它永远存在于临时死区(TDZ)中,因为从未对其执行过规范的InitializeBinding操作。(变量是“绑定”的环境中的对象[这里还有其它种类的绑定以及]。)与通过所创建的变量绑定var,通过创建的那些let可以被未初始化。这是一个例子:

{
    // `x` is *declared* upon entry to this scope, but not *initialized* yet
    x = 5; // Fails because the `x` binding isn't initialized yet
    let x;
}
Run Code Online (Sandbox Code Playgroud)

同样,您的确切示例只能在类似Chrome控制台的控制台中使用。如果new Set(4)没有引发错误,则该行let someSet = new Set(4);将按以下顺序执行这些操作:

  1. 声明(但不初始化)变量(绑定) someSet
  2. 评估初始化器 new Set(4)
  3. 使用#2的结果值初始化变量

问题在于,由于new Set(4)引发了错误,因此从未发生过步骤3。在正常环境中,该错误将使您超出someSet声明的范围,但不在Chrome的控制台中。结果,您根本无法使用someSet,因为您无法再次声明它(它已经被声明),并且您无法读取它的值(它没有一个,它没有被初始化),并且您可以不要向其写入值(因为执行此操作的SetMutableBinding会检查变量是否已初始化,如果尚未初始化,则失败-因为这就是TDZ的工作方式)。