托管 let, const

Hosting of let, const

/* Hoisting exampe - let */
let a = 100;
{
 console.log(a); // 100
}
{
 console.log(a); // ReferenceError: a is not defined
 let a = 50;
}

/* Hoisting took place in {}. */
{
 let a=100;
 console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined

首先,我知道 letconst 有一个 块作用域
编译发生在 执行上下文 单元中,并且 提升 发生在创建 LexicalEnvironment 时。
执行上下文是通过执行 globalfunctioneval code.

constlet 的提升不应在 globalfunctioneval 代码单元?
(貌似并没有发生吊装,不过这纯粹是多亏了TDZ的帮助,内部都有const和let吊装。)

如果引擎在创建 执行上下文 时遇到块 {/* code */}(而不是函数),引擎是否将块的新作用域添加到 [[Scope]]

当一个块是 first encountered (with the {), a new execution context is created, which creates a new empty Lexical Environment (which is basically a container mapping variable names in the current immediate scope to their values). The engine then iterates through 时,所有在直接块中用 constlet 声明的变量都被初始化。 (但是,尽管已初始化,但在引擎实际遇到 const <variableName>let <variableName> 行 - TDZ 之前它们不可引用)

因此,普通块 do 创建一个新作用域,如果紧邻该块内的任何语句使用 const 或 [=13= 声明变量,该作用域将被填充].

您可以在调试器中看到这一点:

/* Hoisting took place in {}. */
{
    debugger;
    let a=100;
    console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined

Chrome devtools 中的结果:

(不过,这有点误导 - a 实际上并不包含 undefined,它当时还没有完全创建)

提升 constlet 变量名是因为解释器从 块的开头识别 引用它是非法的直到它们通过 constlet 行完全创建。

这不仅仅是普通的块——任何级别的代码都会导致同样的事情发生(比如在顶层,或者在for块内, 或函数内部)。