【问题标题】:Scoping of function declarations within `with` statements`with` 语句中函数声明的范围
【发布时间】:2020-06-08 02:17:20
【问题描述】:

前言:在 JavaScript 中使用 withdiscouraged 是有充分理由的。它可能导致混乱的代码和前向兼容性问题(例如,将新属性添加到内置对象时)。这个问题不是关于是否应该使用with - 它是关于with 的规范定义的行为。

下面的代码应该工作吗?

let foo = {};
with(foo) {
  function bar() {
    console.log("hello");
  }
}
bar();

它适用于 Chrome 80,但不适用于 Firefox 72:TypeError: bar is not a function

编辑:原来这个错误只在粘贴到 Firefox 控制台 (https://i.imgur.com/WTG3iiX.png) 时发生,而不是在 HTML 文档中运行代码时发生。

但请注意,它是TypeError,而不是ReferenceError(即bar is not defined)。为了确认这一点,我们可以在bar(); 之前添加console.log("bar" in window),并注意在Firefox 中输出true,而如果你在代码之前编写它会输出false。所以在 Firefox 中,上述代码具有将window.bar 设置为undefined 的效果。

这在 Firefox 和 Chrome 中都可以正常工作:

if(true) {
  function bar() {
    console.log("hello");
  }
}
bar();

正如我所料,因为function foo() {...} 声明是函数作用域的。因此,除非with 块作用域有什么奇怪的地方,否则这似乎是一个 Firefox 错误?

【问题讨论】:

    标签: javascript firefox scope with-statement


    【解决方案1】:

    我无法重现 Firefox 73 的问题,因此 Firefox 的行为可能已经改变。

    也就是说,见MDN on the subject of blocks:

    在严格模式下,从 ES2015 开始,块内的函数的作用域仅限于该块。在 ES2015 之前,严格模式下禁止块级函数。

    IIRC,提升规则和块之间的交互未定义,导致不同 JS 引擎中的行为不同。这与其说是 Firefox 错误,不如说是语言本身定义中的错误。

    避免在块中声明函数。

    【讨论】:

    • 感谢您的测试!我刚刚发现此错误仅在出于某种原因粘贴到控制台时出现(在 Firefox 72 和 73 上):i.imgur.com/WTG3iiX.png 在 HTML 文件中时工作正常。所以看起来这只是一个 Firefox 控制台错误。 (仅供参考,我这里的实际用例是破解 JS 来构建 DSL,所以我实际上并没有尝试在我的日常 JS 代码中的块内声明函数范围的函数。)
    猜你喜欢
    • 2020-11-09
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 2015-03-14
    • 2015-04-12
    相关资源
    最近更新 更多