【问题标题】:function hoisting shows different results with and without block scope [duplicate]函数提升显示有和没有块范围的不同结果[重复]
【发布时间】:2019-02-21 04:43:51
【问题描述】:

这是一个例子:

function b() {
  console.log(f); 

  {
    function f() {}
  }
}

b()

我以为会变成:

function b() {
  // hoist to function scope
  function f() {}
  console.log(f); // should output function f
}

function b() {
  console.log(f); // should output reference error
  {
     // just hoist to block scope like this
     function f() {}
  }
}

但它输出未定义,例如 var 提升。为什么?

【问题讨论】:

  • 在 ES2015 之前不允许函数声明,但浏览器仍然支持它,但每个浏览器的做法不同。 ES2015 在附录中描述了这种行为:ecma-international.org/ecma-262/6.0/…。根据上下文(非严格与严格),函数声明基本上被评估为分配函数表达式的变量声明。在严格模式下,此代码会引发错误。

标签: javascript function ecmascript-6 scope hoisting


【解决方案1】:

{} 创建块作用域

JS 引擎会像这样解释你的代码

function b() {
  console.log(f);
  {
    var f = function f() {};
  }
}

b();

因此,由于f 的块范围值在块外不可用。并且由于它被定义为 var 它被提升到父范围(函数 b 的范围)并且结果是未定义的

如果您删除 {}

function b() {
  console.log(f); 
  function f() {}
}

b()

【讨论】:

  • 在第一个例子中应该是var f = ...“它被提升到全局范围” 不,它不是全局的,它被提升到函数的 (b) 范围内。
  • @FelixKling 是的,我只是忘记在从 babel repl 复制后删除 _'s。更新感谢您的意见:)
  • 删除{} 内的function b()。这是因为控制台语句超出了函数 f() 的声明范围
【解决方案2】:

这是由于吊装。 function f() {} 位于块内,因此 console.log(f) 无法访问超出范围的function f() {}。但是,如果您将 console.log(f) 保留在块 {} 内。吊装应该可以了。

【讨论】:

  • 问题是“这里的吊装如何工作”,而您基本上是在说“这是因为吊装”。这并不是对正在发生的事情的真正解释。
猜你喜欢
  • 2017-02-10
  • 2013-11-12
  • 1970-01-01
  • 2017-11-04
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
相关资源
最近更新 更多