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)
有人可以向我解释这件事是如何运作的吗?对于记录,它仅在非严格模式下工作.
谢谢.
我不会声称理解所有的微妙之处,但关键是附件 B 的 \xc2 \xa7B.3.3.1几乎奇怪的扭曲。
\n该代码实际上是这样的,其中是特定于该块的词法环境f1的第二个副本(因此如下):flet
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}\nRun Code Online (Sandbox Code Playgroud)\n当然,由于var提升, 和p都f在代码片段的顶部有效地声明了初始值undefined:
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}\nRun Code Online (Sandbox Code Playgroud)\nB.3.3.1 中的关键位是它将内部值f(我f1在上面调用的)传输到外部值(在下面,F是 string "f",即所声明的函数的名称):
\n\n3. 当对 FunctionDeclaration f求值时,执行以下步骤来代替 14.1.21 中提供的 FunctionDeclaration 求值算法:
\nA。令fenv为正在运行的执行上下文的变量环境。
\nb. 令fenvRec为fenv的环境记录。
\nC。令benv为正在运行的执行上下文的词法环境。
\nd. 令benvRec为 benv 的环境记录。
\ne. 让fobj成为吧!bevRec.GetBindingValue(F,假)。
\nF。履行 !fenvRec.SetMutableBinding( F , fobj , false)。
\nG。返回正常完成(空)。
\n
回想一下,变量环境是函数范围的,但词法环境受到更多限制(到块)。
\n当涉及到尝试在函数声明 {invalid | } 的地方标准化它们时 未指定} (选择您的术语),TC39 有一个非常危险的导航路径,试图标准化行为,同时不破坏可能依赖于过去特定于实现的行为的现有代码(这些行为是相互排斥的,但 TC39 正在尝试冲帐)。
\n