javascript中的范围和关闭奇怪

kst*_*tis 5 javascript closures function hoisting ecmascript-6

这是昨天在TC39上提出的.你可以在这里找到要点:

var p = () => console.log(f);
{
  p(); // undefined
  console.log(f); // function f(){}

  f = 1;

  p(); // undefined
  console.log(f); // 1

  function f(){}

  p(); // 1
  console.log(f); // 1

  f = 2;

  p(); // 1
  console.log(f); // 2
}
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释这件事是如何运作的吗?对于记录,它仅在非严格模式下工作.

谢谢.

T.J*_*der 2

我不会声称理解所有的微妙之处,但关键是附件 B 的 \xc2 \xa7B.3.3.1几乎奇怪的扭曲。

\n

该代码实际上是这样的,其中是特定于该块的词法环境f1的第二个副本(因此如下):flet

\n
var p = () => console.log(f);\n{\n  let f1 = function f(){};;           // Note hoisting\n  p(); // undefined\n  console.log(f1); // function f(){}\n\n  f1 = 1;\n\n  p(); // undefined\n  console.log(f1); // 1\n\n  var f = f1;                          // !!!\n\n  p(); // 1\n  console.log(f1); // 1\n\n  f1 = 2;\n\n  p(); // 1\n  console.log(f1); // 2\n}\n
Run Code Online (Sandbox Code Playgroud)\n

当然,由于var提升, 和pf在代码片段的顶部有效地声明了初始值undefined

\n
var f = undefined;\nvar p = undefined;\np = () => console.log(f);\n{\n  let f1 = function f(){};;           // Note hoisting\n  p(); // undefined\n  console.log(f1); // function f(){}\n\n  f1 = 1;\n\n  p(); // undefined\n  console.log(f1); // 1\n\n  f = f1;                              // !!!\n\n  p(); // 1\n  console.log(f1); // 1\n\n  f1 = 2;\n\n  p(); // 1\n  console.log(f1); // 2\n}\n
Run Code Online (Sandbox Code Playgroud)\n

B.3.3.1 中的关键位是它将内部值f(我f1在上面调用的)传输到外部值(在下面,F是 string "f",即所声明的函数的名称):

\n
\n

3. 当对 FunctionDeclaration f求值时,执行以下步骤来代替 14.1.21 中提供的 FunctionDeclaration 求值算法:

\n

A。令fenv为正在运行的执行上下文的变量环境。

\n

b. 令fenvRecfenv的环境记录。

\n

C。令benv为正在运行的执行上下文的词法环境。

\n

d. 令benvRec为 benv 的环境记录。

\n

e. 让fobj成为吧!bevRec.GetBindingValue(F,假)。

\n

F。履行 !fenvRec.SetMutableBinding( F , fobj , false)。

\n

G。返回正常完成(空)。

\n
\n

回想一下,变量环境是函数范围的,但词法环境受到更多限制(到块)。

\n

当涉及到尝试在函数声明 {invalid | } 的地方标准化它们时 未指定} (选择您的术语),TC39 有一个非常危险的导航路径,试图标准化行为,同时不破坏可能依赖于过去特定于实现的行为的现有代码(这些行为是相互排斥的,但 TC39 正在尝试冲帐)。

\n