为什么我不能在JavaScript中使用concat方法将“argument”对象转换为数组?

时间:2015-04-04 12:42:14

标签: javascript arrays arguments

我试图用另一个数组连接一个arguments对象,我写了这样的代码:

[].concat.call(arguments, newArray)

但它返回[ [object Arguments], ... ],这正是我想要的。我用Google搜索并找到了一些解释,说明为什么我可以通过切片方法执行此操作:How can I convert the "arguments" object to an array in JavaScript?

但在查看规范之后,我在concat方法上找到了相同的定义:

  

注意 concat函数是故意通用的;它不要求它的这个值是一个Array对象。因此,它可以转移到其他类型的对象以用作方法。 concat函数是否可以成功应用于宿主对象是依赖于实现的。

规范在这里:http://es5.github.io/#x15.4.4.4

所以现在我很困惑为什么我无法通过arguments方法将concat对象转换为数组。

1 个答案:

答案 0 :(得分:2)

详细信息可在§15.4.4.4 of the spec中找到。基本上,它首先创建要处理的事物列表,其中列表中的第一个项目是您调用它的对象(this),然后列表中的后续项目是函数的参数。然后它循环遍历列表并处理每个项目。它有一个显式分支,用于该列表中不是数组的项目,该分支的“else”是(步骤5(c)):

  • 否则,E不是数组
    • 使用参数ToString(n)调用A的[[DefineOwnProperty]]内部方法,属性描述符{[[Value]]:E,[[Writable]]:true,[[Enumerable]]:true,[[可配置]]:true}和false。
    • 将n增加1。

所以你可以在非数组上调用concat。它不会失败。但是它并不像处理数组一样处理非阵列数组的事物。

注意Felix's observation这个“只有阵列让他们的条目展开”在ES6中正在发生变化。 concat在对象上使用新的"is concat spreadable" flag来确定它是否应该遍历其条目。我不认为arguments对象会有那个标志(至少,我在§9.4.4中没有看到任何这样的说法),可能是为了避免向后兼容性问题。