JavaScript中的arguments对象是一个奇怪的东西——它在大多数情况下就像一个数组,但实际上它不是一个数组对象。因为它是完全不同的东西,它没有数组中的有用函数。比如forEach, sort, filter和map。

用简单的for循环从arguments对象构造一个新数组非常简单。例如,这个函数对它的参数进行排序:

function sortArgs() {
    var args = [];
    for (var i = 0; i < arguments.length; i++)
        args[i] = arguments[i];
    return args.sort();
}

然而,仅仅为了访问非常有用的JavaScript数组函数,就必须这么做,这是一件相当可怜的事情。是否有一种内置的方法来使用标准库?


当前回答

ES6使用rest参数

如果你能使用ES6,你可以使用:

其他参数

函数sortArgs(…args) { 返回参数。排序(函数(a, b){返回a - b;}); } document.body.innerHTML = sortArgs(12,4,6,8).toString();

你可以从链接中读到

rest形参语法允许我们将不确定数量的实参表示为数组。

如果你对…语法,它被称为扩散运算符,你可以在这里阅读更多。

ES6使用Array.from()

使用Array.from:

函数sortArgs() { return Array.from(arguments).sort(function (a, b) {return a - b;}); } document.body.innerHTML = sortArgs(12,4,6,8).toString();

from简单地将类数组或可迭代对象转换为数组实例。



ES5

你可以在arguments对象上使用Array的slice函数,它会把它转换成一个标准的JavaScript数组。你只需要通过Array的原型手动引用它:

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}

为什么会这样?下面是ECMAScript 5文档本身的一段摘录:

注意:slice函数是有意通用的;它不要求它的this值是一个Array对象。因此,它可以转移到其他类型的对象中作为方法使用。slice函数能否成功应用于主机对象取决于实现。

因此,slice对任何具有length属性的东西都有效,而参数很方便地做到了这一点。


如果array .prototype.slice对你来说太拗口了,你可以使用数组字面量来略写它:

var args = [].slice.call(arguments);

然而,我倾向于认为前一个版本更明确,所以我更喜欢它。滥用数组文字符号会让人觉得很俗气,看起来很奇怪。

其他回答

我建议使用ECMAScript 6展开操作符,它将把尾随参数绑定到数组。有了这个解决方案,你不需要触及arguments对象,你的代码将被简化。这个解决方案的缺点是它不能在大多数浏览器上运行,所以你必须使用JS编译器,比如Babel。在底层,Babel使用for循环将参数转换为Array。

function sortArgs(...args) {
  return args.sort();
}

如果你不能使用ECMAScript 6,我建议你看看其他的答案,比如@Jonathan Fingland

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}

ES6使用rest参数

如果你能使用ES6,你可以使用:

其他参数

函数sortArgs(…args) { 返回参数。排序(函数(a, b){返回a - b;}); } document.body.innerHTML = sortArgs(12,4,6,8).toString();

你可以从链接中读到

rest形参语法允许我们将不确定数量的实参表示为数组。

如果你对…语法,它被称为扩散运算符,你可以在这里阅读更多。

ES6使用Array.from()

使用Array.from:

函数sortArgs() { return Array.from(arguments).sort(function (a, b) {return a - b;}); } document.body.innerHTML = sortArgs(12,4,6,8).toString();

from简单地将类数组或可迭代对象转换为数组实例。



ES5

你可以在arguments对象上使用Array的slice函数,它会把它转换成一个标准的JavaScript数组。你只需要通过Array的原型手动引用它:

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}

为什么会这样?下面是ECMAScript 5文档本身的一段摘录:

注意:slice函数是有意通用的;它不要求它的this值是一个Array对象。因此,它可以转移到其他类型的对象中作为方法使用。slice函数能否成功应用于主机对象取决于实现。

因此,slice对任何具有length属性的东西都有效,而参数很方便地做到了这一点。


如果array .prototype.slice对你来说太拗口了,你可以使用数组字面量来略写它:

var args = [].slice.call(arguments);

然而,我倾向于认为前一个版本更明确,所以我更喜欢它。滥用数组文字符号会让人觉得很俗气,看起来很奇怪。

这里有一个简洁明了的解决方案:

函数argsToArray() { 返回Object.values(参数); } //使用实例 console.log ( argsToArray(1, 2, 3, 4, 5) .map(arg => arg*11) );

对象。values()将以数组的形式返回对象的值,由于arguments是一个对象,它本质上将参数转换为数组,从而为您提供数组的所有辅助函数,如map、forEach、filter等。

如果你正在使用jQuery,在我看来,下面的代码更容易记住:

function sortArgs(){
  return $.makeArray(arguments).sort();
}

在ECMAScript 6中,不需要使用像Array.prototype.slice()这样丑陋的hack。您可以使用扩展语法(…)。

(函数(){ console.log(参数[…]); }(1,2,3))

这看起来可能很奇怪,但其实相当简单。它只是提取参数的元素并将它们放回数组。如果你还是不明白,请看下面的例子:

console.log([1, ...[2, 3], 4]); console.log([...[1, 2, 3]]); console.log([...[...[...[1]]]]);

注意,它在一些较老的浏览器(如IE 11)中不起作用,所以如果你想支持这些浏览器,你应该使用Babel。