这是昨天在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吊起,pf都可以有效地在代码片段的顶部声明为初始值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/

10-10 12:44