javascript - `with` 语句中函数声明的范围
问题描述
前言:在 JavaScript 中不鼓励with
使用 of是有充分理由的。它可能导致混淆代码和前向兼容性问题(例如,将新属性添加到内置对象时)。这个问题不是关于是否应该使用 - 它是关于.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 文档中运行代码时发生。
但请注意它是 a TypeError
,而不是ReferenceError
(ie bar is not defined
)。为了确认这一点,我们可以添加console.log("bar" in window)
before bar();
,并注意在 Firefox 中输出 true,而如果你在代码之前编写它,它会输出 false。所以在 Firefox 中,上面的代码具有设置window.bar
为undefined
.
这在 Firefox 和 Chrome 中都可以正常工作:
if(true) {
function bar() {
console.log("hello");
}
}
bar();
正如我所预料的那样,因为function foo() {...}
声明是函数范围的。因此,除非块作用域有什么奇怪的地方with
,否则这似乎是一个 Firefox 错误?
解决方案
我无法重现 Firefox 73 的问题,因此 Firefox 的行为可能已经改变。
也就是说,请参阅MDN 关于 blocks 的主题:
在严格模式下,从 ES2015 开始,块内的函数的作用域是该块。在 ES2015 之前,严格模式下禁止块级函数。
IIRC,提升规则和块之间的交互未定义,导致不同 JS 引擎中的行为不同。这与其说是 Firefox 的错误,不如说是语言本身定义中的错误。
避免在块中声明函数。
推荐阅读
- java - DBFField 数字类型
- ios - CoreData:如何在 `NSManagedObjectContextObjectsDidChange` 中创建和保存对象?
- mysql - 选择查询特定列不检索数据
- r - 使用批处理文件运行多行 R 脚本时如何保存工作区
- android - 将图像插入画布
- javascript - 如何在 Bootstrap 4 的输入组中使用图像
- hadoop - 一个巨大的文件如何来自 HDFS 之外?
- arrays - 使用 Sumproduct 查找最大值
- c# - 如果不使用数据提供程序,则缺少新对象 - Audit.Net
- javascript - 替换 webpack 包中的变量而不破坏源映射和重建