这是昨天在TC39上提出的。您可以找到要点here:
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
}
有人可以告诉我这件事是如何工作的吗?为了记录,仅在非严格模式下使用。
谢谢你。
最佳答案
我不会要求理解所有的微妙之处,但关键是附件B的§B.3.3.1几乎是奇怪的扭曲。
该代码实际上就是这样,其中f1
是特定于该块的词法环境的f
的第二个副本(因此,下面的let
):
var p = () => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
var f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
当然,由于有了var
吊起,p
和f
都可以有效地在代码片段的顶部声明为初始值undefined
:var f = undefined;
var p = undefined;
p = () => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
B.3.3.1中的关键位是它将内部f
(我在上面称为f1
)的值传输到外部"f"
(在下面,F是字符串ojit_code,即要声明的函数的名称) ):回想一下变量环境是函数范围的,但是词法环境更受约束(仅限于该块)。
尝试在{无效|无效的地方对函数声明进行规范化未指定}(选择您的用语),TC39具有非常奸诈的路径来导航,尝试使行为标准化,同时又不破坏过去可能依赖于实现特定行为的现有代码(这是相互排斥的,但是TC39是试图取得平衡)。
关于javascript - JavaScript中的作用域和闭合奇数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40888805/