以下代码打印 1
在 OSX 上的 Safari 13.0.4 中。
let set = new Set
for(let x = 0; x < 2; x++) {
function f() {}
set.add(f)
}
console.log(set.size) // 1 in Safari non-strict mode
还:
let set = new Set
for(let x = 0; x < 2; x++) {
function f() {}
f.test = x
set.add(f)
}
console.log(set.size); // 1 in Safari
for(let x of set) console.log(x.test) // 1 in Safari non-strict mode
和:
let set = new Set;
for(let x = 0; x < 2; x++) {
var v = (function () {})
set.add(v);
}
console.log(set.size); // 2 in Safari non-strict mode
此行为是否与 section 13.7.4.8 兼容? (见下文)的规范?
请注意:Node 13.9.0、Chrome 80.0.3987.122 和 Brave 1.3.118 打印
2
.13.7.4.8 规范:
(4.b 似乎相关)
The abstract operation ForBodyEvaluation with arguments test,
increment, stmt, perIterationBindings, and labelSet is
performed as follows:
1. Let V = undefined.
2. Let status be CreatePerIterationEnvironment(perIterationBindings).
3. ReturnIfAbrupt(status).
4. Repeat
a. If test is not [empty], then
i. Let testRef be the result of evaluating test.
ii. Let testValue be GetValue(testRef).
iii. ReturnIfAbrupt(testValue).
iv. If ToBoolean(testValue) is false, return NormalCompletion(V).
b. Let result be the result of evaluating stmt.
c. If LoopContinues(result, labelSet) is false, return d.
Completion(UpdateEmpty(result, V)).
d. If result.[[value]] is not empty, let V = result.[[value]].
e. Let status be CreatePerIterationEnvironment(perIterationBindings).
f. ReturnIfAbrupt(status).
g. If increment is not [empty], then
i. Let incRef be the result of evaluating increment.
ii. Let incValue be GetValue(incRef).
iii. ReturnIfAbrupt(incValue).
最佳答案
是的,这是 Safari[1] 中的一个错误。但是,正如您所注意到的,它只发生在 在全局(或 eval
)范围内 和 仅在草率模式下 .
一般来说,这些绝对应该是不同的函数实例,而不是被提升到 block 之外。然而,作为浏览器的 Safari 确实实现了规范附录 B3.3 中的 block 级函数声明 Web Legacy Compatibility Semantics(详见 here)。在 ES6 和 ES7 中,但这些确实只适用于函数内部的 block 语句。仅自 ES8 起,它们也被指定用于全局和评估范围内的声明实例化。
似乎 Safari 还没有采用 ES8 的更改,并且保留了自己的(不符合)pre-ES6 semantics对于全局范围内的 block 范围声明,它们会完全提升声明。
1:大概#201695或 #179698 . “我们不在全局范围内支持这一点。我们在函数内部支持它,我相信 eval。我们仍然需要在全局范围内实现它。”
关于javascript - 这种 Safari 行为是否违反了 ECMAScript 规范?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60416842/