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数组函数,就必须这么做,这是一件相当可怜的事情。是否有一种内置的方法来使用标准库?


当前回答

尽管rest参数工作得很好,但如果出于某种原因希望继续使用参数,请考虑

function sortArgs() {
  return [...arguments].sort()
}

[…arguments]可以被认为是Array.from(arguments)的一种替代方法,后者也能很好地工作。

ES7的一个替代方案是数组理解:

[for (i of arguments) i].sort()

如果你想在排序之前处理或过滤参数,这可能是最简单的:

[for (i of arguments) if (i % 2) Math.log(i)].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。

使用array .from(),它接受一个类似数组的对象(比如参数)作为参数,并将其转换为数组:

(函数(){ console.log (Array.from(参数)); }(1,2,3));

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

下面是将参数转换为数组的几个方法的基准测试。

对我来说,对于少量的争论,最好的解决办法是:

function sortArgs (){
  var q = [];
  for (var k = 0, l = arguments.length; k < l; k++){
    q[k] = arguments[k];
  }
  return q.sort();
}

其他情况:

function sortArgs (){ return Array.apply(null, arguments).sort(); }

Arguments对象只能在函数体中使用。虽然你可以像数组一样索引Arguments对象,但它不是数组。除了长度,它没有任何数组属性。

// function arguments length 5 function properties(a,b,c,d,e){ var function_name= arguments.callee.name var arguments_length= arguments.length; var properties_length= properties.length; var function_from= properties.caller.name; console.log('I am the function name: '+ function_name); console.log('I am the function length, I am function spacific: '+ properties_length); console.log('I am the arguments length, I am context/excution spacific: '+ arguments_length); console.log('I am being called From: '+ function_from ); } // arguments 3 function parent(){ properties(1,2,3); } //arguments length 3 because execution spacific parent();

虽然它可以像数组一样被索引,就像你在这个例子中看到的:

函数添加(){ var和= 0; (var = 0;我< arguments.length; + +) { Sum = Sum +参数[i]; } 返回总和; } console.log(添加(1、2、3);

然而,Arguments对象不是一个数组,除了长度之外没有任何其他属性。

您可以将arguments对象转换为一个数组,然后可以访问arguments对象。

有很多方法可以访问函数体中的arguments对象,包括:

你可以调用array . prototype .slice.call方法。

Array.prototype.slice.call(参数)

function giveMeArgs(arg1,arg2){ var args = Array.prototype.slice.call(arguments); 返回参数 } console.log( giveMeArgs(1,2));

你可以使用数组文字

[] .slice.call(参数)。

function giveMeArgs (arg1, arg2)可不, var args = [].slice.call(参数); return args; 出于美观 console.log(givemeargs(1,2))

你可以使用Rest…

函数给出MeArgs(...参数){ 返回参数; } console.log(giveMeArgs(1,2))

你可以用spread[…]

function giveMeArgs()可不, var args=[…参数]; return args; 出于美观 console.log (giveMeArgs (1,2));

你可以使用Array.from()

函数giveMeArgs () ( 瓦尔·阿格斯=阵列。 重返args; ) 游戏机。log (giveMeArgs (1,2));

同样值得参考的是这个Bluebird承诺库wiki页面,它展示了如何以一种使函数在V8 JavaScript引擎下可优化的方式管理参数对象到数组:

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

此方法用于支持var args = [].slice.call(arguments);。作者还展示了构建步骤如何帮助减少冗余。