Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/462.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 这种Safari行为是否违反了ECMAScript规范?_Javascript_Macos_Safari - Fatal编程技术网

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

Javascript 这种Safari行为是否违反了ECMAScript规范?,javascript,macos,safari,Javascript,Macos,Safari,以下代码在OSX上的Safari 13.0.4中打印1 let set=新集合 for(设x=0;x

以下代码在OSX上的Safari 13.0.4中打印
1

let set=新集合
for(设x=0;x<2;x++){
函数f(){}
集合。添加(f)
}

console.log(set.size)//1在Safari非严格模式下
据我所知,在a中放置函数声明的代码应遵循的规范(我用粗体表示):

对块或CaseBlock求值时,将创建一个新的声明性环境记录,并在环境记录中实例化块中声明的每个块作用域变量、常量、函数或类的绑定

其中一个步骤显式处理函数声明,这取决于,而函数声明又取决于。。。这将创建一个新的对象

所有这些都发生在评估阶段。您对规范的引用说明每次迭代都会进行求值,因此应该在每次迭代中新创建函数对象

执行上的差异 该规范中有一节介绍了与此相关的实现差异。它说:

在ECMAScript 2015之前,ECMAScript规范没有将FunctionDeclaration的出现定义为块语句的StatementList元素。然而,对这种形式的FunctionDeclaration的支持是允许的扩展,大多数浏览器托管的ECMAScript实现都允许这样做。不幸的是,这些声明的语义在这些实现中有所不同。由于这些语义差异,使用块级函数声明的现有web ECMAScript代码仅在浏览器实现之间可移植,前提是其使用仅取决于所有浏览器实现对此类声明的语义交集。以下是属于该交集语义的用例:

  • 函数被声明,并且仅在单个块中引用

    • BindingIdentifier为名称f的一个或多个FunctionDeclaration出现在封闭函数g的函数代码中,并且该声明嵌套在块中
    • 在g的函数代码中,没有其他不是
      var
      声明的f声明
    • 所有作为IdentifierReference出现的f都在包含f声明的块的StatementList中

  • 现在,当代码不是顶级脚本,而是放在函数体中时,您问题中的案例的行为符合规范(打印2)。在这种情况下,我们处于情况1(在上面的报价中)。但当脚本是全局脚本时,这一点不适用。因此,我们确实看到了偏差行为…

    是的,这是Safari中的一个bug[1]。但是,正如您所注意到的,它只在全局(或
    eval
    )范围内出现,并且只在草率模式下出现

    一般来说,这些都应该是不同的函数实例,而不是被提升到块之外。然而,Safari作为一种浏览器,确实实现了规范附录B3.3中的块级功能声明Web遗留兼容性语义(有关详细信息,请参阅)。但在ES6和中,它们只适用于函数内部的块语句。只是因为,它们也被指定用于全局和eval范围中的声明实例化

    Safari似乎还没有采用ES8的更改,并且在全局范围内保留了自己的(不兼容的)块范围声明,在全局范围内它们完全提升了声明


    1:可能吧。“我们在全局范围内不支持它。我们确实在函数内部支持它,我相信eval。我们仍然需要在全局范围内实现它。”

    我认为一个更密切(或同样密切)的部分应该是处理函数语句行为的部分,它可以处理函数语句的行为。ES规范中可能对块内函数语句进行了特殊处理,使得每个块只创建一个函数,而不是该块代码的每次迭代。在ES5中,块级函数是未定义的行为,浏览器支持它们作为ES5规范之外的扩展。另请参见@Ben Ah good know。那么,这可能不是违反§13.7.4.8,而是违反了附录B3.3。当您使用正常函数(立即调用)包装整个代码时,您在Safari中是否会得到相同的行为,或者这是特定于将此代码放在脚本的顶层吗?@Bergi
    f
    在Safari non-strict.Ah中似乎被提升到块外,所以这只发生在全局范围内?好的调用@trincott规范是否基本上在Web遗留兼容性语义中编码,所有已知实现特定行为的交叉点,以及在非严格模式下与这些行为的任何偏差是否不符合要求?@Ben附录标准化了最有用的行为,具有最高的Web兼容性(即保持现有代码正常工作)并且仍然能够合理地实施,并且不会偏离正确的行为太远。它并不完全是已知实现的交叉点。但是,是的,我认为这些语义的任何偏离都是不符合的:目标是让引擎根本不实现这些(因为它不执行来自web的脚本),或者如果他们需要实现兼容性特性,他们应该完全按照附录B中的标准来做。