javascript - 这种 Safari 行为是否违反了 ECMAScript 规范?

标签 javascript macos safari

以下代码打印 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/

相关文章:

macos - macOS 上redis 安装在什么位置?

linux - 在多个文件上运行命令并保持相同的名称

javascript - iOS Safari 随机调整大小和滚动问题

javascript - 使用 JavaScript 将最新的数组索引存储在单独的数组中

javascript - 禁用 Chrome 网络安全后 CORS 仍然强制执行吗?

javascript - NodeJS 中的 "done"属性是什么?

javascript - 无法在 Angular 中创建抽象类的实例,但在 JS 中工作正常

swift - C 语言的 FTDI D2XX API 在命令行控制台上工作,但在 macOS 上由 Xcode 和 Swift 编程构建的应用程序中始终返回零

javascript - HTML5 视频 : canPlayType() is not working in safari

html - 在 Win7 上的 Safari 中居中输入占位符