ES6中的arguments对象是否应该是可迭代的?

15
在ES6中,我尝试将传递给Set构造函数的arguments对象作为可迭代对象使用。在IE11和Chrome 47中运行良好,但在Firefox 43中不起作用(会抛出TypeError:arguments is not iterable)。我已经查阅了ES6规范,但没有找到关于arguments对象是否应该是可迭代对象的定义。
以下是我尝试做的示例:
function destroyer(arr) {
  var removes = new Set(arguments);
  return arr.filter(function(item) {
    return !removes.has(item);
  });
}

// remove items 2, 3, 5 from the passed in array
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
log(result);

提醒一下,我知道有各种解决此代码的方法,例如将参数对象复制到真实数组中或使用剩余参数。这个问题是关于ES6中的arguments对象是否应该是可迭代的,可以在任何需要可迭代的地方使用。


2
这是一个已知的 FF bug:The arguments object should support the ES6 @@iterator protocol - apsillers
@apsillers - 看起来代码已经被编写以修复它(上个月),并且正在进行审核和测试的过程中。 - jfriend00
1个回答

9

我认为这是FF实现中的一个错误。

根据9.2.12 FunctionDeclarationInstantiation(func, argumentsList)一节所述,

如果argumentsObjectNeeded为true,则

a) 如果strict为true或simpleParameterList为false,则

==> i) 让ao成为CreateUnmappedArgumentsObject(argumentsList)。

b) 否则,

==> i) 注意:映射参数对象仅适用于没有剩余参数、任何参数默认值初始化程序或任何解构参数的非严格函数。

==> ii) 让ao成为CreateMappedArgumentsObject(func, formals, argumentsList, env)。

无论是CreateMappedArgumentsObject还是CreateUnmappedArgumentsObject都有

执行DefinePropertyOrThrow(obj,@@iterator,PropertyDescriptor {[[Value]]:%ArrayProto_values%,[[Writable]]: true,[[Enumerable]]: false,[[Configurable]]: true})。

这意味着@@iterator属性实际上应该在arguments对象上定义。


为了明确地证明它没有被定义:(function(a) { return arguments[Symbol.iterator] })(1)在Firefox中产生的是undefined,但在其他浏览器中是一个函数。 - apsillers
2
现在我有了更好的搜索方向,于是我在Firefox的bug报告中搜索到了这里:The arguments object should support the ES6 @@iterator protocol。看起来它正在发布过程中(上个月写入修复该漏洞的代码)。 - jfriend00
感谢您指出 ES6 规范中正确的位置。我本来期望 arguments 对象的描述会提到 @@iterator,但实际上并没有。规范本身似乎更加过程化而不是面向对象,这似乎有点讽刺。 - jfriend00
错误修复现已发布,适用于Firefox 46。 - jfriend00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接