3

我认为这是一个旧的 Javascript 行为(Crockford 说这是一个设计错误),在函数内部arguments就像一个数组,除了它不是一个真正的数组,所以不能在它上面调用数组方法:

function foo() { console.log(arguments.slice(1)) }   // won't work
foo(1,2,3);

而且我只是在最新的 Firefox 和 Chrome 上尝试过,但两者都无法正常工作。所以我们可能不得不使用

function foo() { console.log(Array.prototype.slice.call(arguments, 1)) }
foo(1,2,3);

但是为什么不在arguments现代 JavaScript 中创建一个真正的数组呢?可能不应该有任何依赖于arguments不是真正数组的程序?现在不把它变成一个真正的数组的原因可能是什么?

我能想到的一个原因是,如果程序员开始将其视为数组,那么代码将无法在旧版浏览器中运行,但 ECMA-5 中的其他内容也无法在旧版浏览器中运行。

4

5 回答 5

4

直到 ECMAScript 5 开发的最后阶段,argument 对象才会继承所有的 Array.prototype 方法。但是 2009 年 9 月 TC39 批准的 ES5“最终草案”并没有这个功能。

2009 年 8 月,Apple 的 Oliver Hunt 将其发布到 es5-discuss 邮件列表

https://mail.mozilla.org/pipermail/es5-discuss/2009-August/003112.html

上周五,我实现了使 Arguments 对象从 WebKit 中的 Array 继承的逻辑,并且很快发现它
与 Prototype.js 严重不兼容……这至少破坏了许多 Apple 网站和 Nasa.gov —— .. . 由于这些站点损坏,由相当主要的库中的一个主要兼容性问题引起,尝试将 类似数组的行为
改进为参数似乎是不可行的。

TC39 的其余部分同意 Oliver 的评估,并从最终草案中删除了该功能。

也许,这样的代码已经从网络上消失了,以至于提议的 ES5 解决方案今天可以工作。然而,这并不重要,因为 ES6 中的 rest 参数是解决问题的更好方法,并且是一个全新的语法特性,不会与现有代码有任何向后兼容性问题。

于 2012-11-02T05:30:01.793 回答
1

有些在线网站不依赖于arguments数组,例如使用旧版本 Prototype 和 script.aculo.us 的网站。这意味着任何改变它的浏览器(ES4 包括这个,它与 Futhark 中的许多其他部分一起实现,在 9.5-10.10 的 Opera 中使用)都会破坏这些网站,并且市场强烈鼓励不要破坏网站(任何考虑到许多网站很少更新,出于显而易见的原因,会破坏网站的浏览器不会被关心这些网站的用户使用)。

于 2012-11-01T20:48:37.860 回答
0

在下一版本的 ECMAScript 中,这个问题(以及其他几个问题)正在使用 rest 参数解决。

function foo(...rest) {
    console.log(rest.slice(1))
}

foo(1, 2, 3);

与 不同arguments,其余参数将是真正的数组,因此这将起作用。

休息参数可以做得更多。在上面的示例中,您可能希望将第一个参数用于一件事,并将其后的所有内容用于其他事情。你可以这样做:

function foo(first, ...rest) {
    console.log('first: ', first);
    console.log('rest: ', rest);
}

foo(1, 2, 3);

这将记录:

第一个:1

休息:[2, 3]

提案:http ://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters

于 2012-11-01T20:42:16.997 回答
0

这主要是因为据我所知它需要是只读的。

如果它是一个数组,那么它必须是一个只读数组,这意味着我们必须摆脱 push、pop、splice 等......任何修改数组的方法。至此,尽管我同意像 slice 这样的其他方法可能会派上用场,但它已经是一种数据结构,其要求与 javascript Array 不同。

我认为他们不应该说它是一个类似数组的对象,在我看来,它只是一个不同的对象,恰好有一个名为长度的属性(与数组相同)。

于 2012-11-01T20:43:44.983 回答
0

是什么阻止了现代实现不将参数视为真正的数组?

实现什么?EcmaScript 5.1 规范,是的。然而,有相当准确的规定,应该有一个arguments绑定以及这样的Arguments对象是什么。

此外,一个Arguments对象并不是一个真实的Array,因为它在其属性方面有一些非常特殊的行为。[[Get]]、[[Delete]] 等被覆盖以反映函数参数变量。如果它是一个数组,则在这样的对象上调用push等可能会造成严重破坏。splice

于 2012-11-01T20:54:36.030 回答