2

我正在观看Crockford on Javascript - Act III: Function the Ultimate大约 41 分 26 秒。他屏幕上的代码使用arguments.slice()方式对我来说会导致错误

function curry(func){
    var args = arguments.slice(1);
    ...
}

他是这样解释的:

我将首先得到一个参数数组,除了第一个,因为第一个是一个函数,我不需要那个。在这种情况下,我假设我在 ES5 上,所以我没有做可怕的 Array.prototype.apply()把戏。

问题是运行arguments.slice()会导致这个错误:

Uncaught TypeError: arguments.slice is not a function

我正在测试肯定有 ES5 的现代浏览器!我可以让代码工作的唯一方法是如果我使用一些“可怕的”技巧,(正如他所说的那样)例如Array.prototype.slice.apply(arguments, [1])[].slice.call(arguments, 1);.

他只是误会了吗?他的幻灯片有错字吗?为什么arguments.slice()在我的 ES5 浏览器中不起作用?

4

3 回答 3

5

引用TC39 成员 Allen Wirfs-Brock 的话:

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

让 arguments 对象继承自 Array 原型实际上是有计划的,但在实践中它破坏了 web。因此,在正式出版之前,它已从最终修订版中删除。


如今,随着 ECMAScript 2015(又名 ES6)标准化,最好的方法是使用剩余参数

function curry(func, ...args) {
  // ...
}

相当于 ES5:

function curry(func) {
  var args = [].slice.call(arguments, 1);
  // ...
}

此功能已在 Firefox 和 Edge 中原生可用,如果您使用 JavaScript 编译器(例如Babel ),则可以在任何地方使用。

于 2015-06-27T02:28:44.240 回答
0

作为arguments类似数组,您可以使用:

function fn() {
  const args = Array.from(arguments)
}

(如果你有PolyfillBabel

于 2018-06-04T13:22:24.537 回答
-2

arguments对象不是数组。它类似于 Array(类似 Array),但除了 . 之外没有任何 Array 属性length

您必须先使用上述技巧将其转换为数组。

var slice = Array.prototype.slice;
function curry(func){
    var args = slice.call(arguments, 1); // converts into array
}

arguments 将继承数组中的所有原型方法,但在最终草案中,此功能已被删除。

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

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

所以最终,他们没有强迫每个人更改代码以避免破坏网页,而是恢复了这一更改。因此,即使在 ES5 中,您仍然需要应用上述技巧将参数转换为实际数组。

于 2015-06-27T01:57:20.997 回答