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);

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


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

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

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

// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }

一些数组方法故意不要求目标对象是一个实际的数组。它们只要求目标具有名为length和indexes的属性(必须为零或更大的整数)。

[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})

这是一个非常老的问题,但我认为我有一个解决方案,它比以前的解决方案更容易输入,并且不依赖于外部库:

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

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

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

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(); }

Use:

function sortArguments() {
  return arguments.length === 1 ? [arguments[0]] :
                 Array.apply(null, arguments).sort();
}

阿雷(arg1, arg2, ..)

数组(str1)返回[str1]

Array(num1)返回一个包含num1个元素的数组

您必须检查参数的数量!

数组中。切片版(较慢):

function sortArguments() {
  return Array.prototype.slice.call(arguments).sort();
}

数组中。推送版本(比切片慢,比切片快):

function sortArguments() {
  var args = [];
  Array.prototype.push.apply(args, arguments);
  return args.sort();
}

移动版本(较慢,但小尺寸更快):

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

数组中。Concat版本(最慢):

function sortArguments() {
  return Array.prototype.concat.apply([], arguments).sort();
}

同样值得参考的是这个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);。作者还展示了构建步骤如何帮助减少冗余。


另一个答案。

使用黑魔法咒语:

function sortArguments() {
  arguments.__proto__ = Array.prototype;
  return arguments.slice().sort();
}

Firefox、Chrome、Node.js、IE11都可以。


本什马克3方法:

function test()
{
  console.log(arguments.length + ' Argument(s)');

  var i = 0;
  var loop = 1000000;
  var t = Date.now();
  while(i < loop)
  {
      Array.prototype.slice.call(arguments, 0); 
      i++;
  }
  console.log(Date.now() - t);


  i = 0,
  t = Date.now();
  while(i < loop)
  {
      Array.apply(null, arguments);
      i++;
  }
  console.log(Date.now() - t);

  i = 0,
  t = Date.now();
  while(i < loop)
  {
      arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
      i++;
  }
  console.log(Date.now() - t);
}

test();
test(42);
test(42, 44);
test(42, 44, 88, 64, 10, 64, 700, 15615156, 4654, 9);
test(42, 'truc', 44, '47', 454, 88, 64, '@ehuehe', 10, 64, 700, 15615156, 4654, 9,97,4,94,56,8,456,156,1,456,867,5,152489,74,5,48479,89,897,894,894,8989,489,489,4,489,488989,498498);

结果呢?

0 Argument(s)
256
329
332
1 Argument(s)
307
418
4
2 Argument(s)
375
364
367
10 Argument(s)
962
601
604
40 Argument(s)
3095
1264
1260

享受吧!


在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。


我建议使用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();
}

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

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

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


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


尝试使用Object.setPrototypeOf()

解释:将参数的原型设置为Array.prototype

函数toArray() { 返回对象。Array.prototype setPrototypeOf(参数) } console.log (toArray(“abc”,123年,{def: 456}, [0, [7, [14]]]))


说明:取参数的每个索引,将item放入数组中对应的数组索引处。

也可以使用Array.prototype.map()

function toray () return键[]文件夹。电话(论据,(_,k,a) => a[k]) 的 控制台日志(toArray(“abc”,123,{def: 456} [0, [7], [14]])


说明:取参数的每个索引,将item放入数组中对应的数组索引处。

循环的. .

函数toArray() { Let arr = [];For (let prop of arguments) arr.push(prop);返回加勒比海盗 } console.log (toArray(“abc”,123年,{def: 456}, [0, [7, [14]]]))


或Object.create ()

说明:创建对象,将对象的属性设置为每个参数索引处的项;设置创建对象的原型为Array.prototype

函数toArray() { Var obj = {}; For (var prop in arguments) { Obj[道具]= { 价值:参数(道具) 可写:没错, 可列举的:真的, 可配置:真 } } 返回Object.create(数组。原型,obj); } console.log (toArray(“abc”,123年,{def: 456}, [0, [7, [14]]]))


尽管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()

 function x(){
   var rest = [...arguments]; console.log(rest);return     
   rest.constructor;
 };
 x(1,2,3)

我尝试了简单的破坏技巧


function sortArg(){
var args = Array.from(arguments); return args.sort();
}

函数sortArg () ( 瓦尔·阿格斯=阵列。 重返args sort (); ) ”,类游戏机。log (sortArg(20、1、2、目标、88、’19’、39、’d’’z’’ak’’bu’、90);


Lodash:

var args = _.toArray(arguments);

在行动:

(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)

生产:

[2,3]

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));


你可以创建一个可重用的函数来使用任何参数,最简单的是这样的:

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

sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];

扩展语法可以在ES6及以上版本中使用…

但是如果你想使用与ES5及以下版本兼容的东西,你可以使用Array.prototype.slice。调用,所以你的代码看起来像这样:

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

sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];

还有一些其他方法可以做到这一点,例如使用array. from或循环参数并将它们分配给一个新数组…


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

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

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