453

JavaScript 中的arguments对象是一个奇怪的缺陷——在大多数情况下它的行为就像一个数组,但它实际上并不是一个数组对象。因为它完全是另外一回事,它没有Array.prototypeforEach, 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 数组函数而不得不这样做是一件相当可怜的事情。有没有使用标准库的内置方法?

4

21 回答 21

753

ES6 使用剩余参数

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

休息参数

function sortArgs(...args) {
  return args.sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();

正如您在链接中所读到的

剩余参数语法允许我们将不定数量的参数表示为一个数组。

如果您对语法感到好奇...,它被称为扩展运算符,您可以在此处阅读更多内容。

ES6 使用 Array.from()

使用Array.from

function sortArgs() {
  return Array.from(arguments).sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();

Array.from只需将类 Array 或 Iterable 对象转换为 Array 实例。



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属性的东西,这arguments很方便。


如果Array.prototype.slice对您来说太多了,您可以使用数组文字稍微缩写它:

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

但是,我倾向于觉得前一个版本更明确,所以我更喜欢它。滥用数组字面量表示法让人感觉很笨拙,看起来很奇怪。

于 2009-06-07T00:10:20.227 回答
40

还值得参考这个 Bluebird promises library wiki 页面,该页面显示了如何以arguments使函数在 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);. 作者还展示了构建步骤如何帮助减少冗长。

于 2014-06-03T09:11:00.670 回答
29
function sortArgs(){ return [].slice.call(arguments).sort() }

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

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

[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
于 2009-06-09T18:29:38.460 回答
12

采用:

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

Array(arg1, arg2, ...)返回[arg1, arg2, ...]

Array(str1)返回[str1]

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

您必须检查参数的数量!

Array.slice版本(较慢):

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

Array.push版本(比 slice 慢,快):

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

Array.concat版本(最慢):

function sortArguments() {
  return Array.prototype.concat.apply([], arguments).sort();
}
于 2013-10-27T14:39:14.820 回答
9

如果您使用的是 jQuery,我认为以下内容更容易记住:

function sortArgs(){
  return $.makeArray(arguments).sort();
}
于 2009-06-07T00:19:43.217 回答
9

在 ECMAScript 6 中,不需要使用像Array.prototype.slice(). 您可以改为使用扩展语法 ( ...)

(function() {
  console.log([...arguments]);
}(1, 2, 3))

它可能看起来很奇怪,但它相当简单。它只是提取arguments' 元素并将它们放回数组中。如果您仍然不明白,请参阅以下示例:

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

请注意,它不适用于 IE 11 等一些较旧的浏览器,因此如果您想支持这些浏览器,则应使用Babel

于 2016-01-24T17:04:18.273 回答
5

这是将参数转换为数组的几种方法的基准。

至于我,少量论点的最佳解决方案是:

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(); }
于 2013-07-03T09:05:18.823 回答
4

我推荐使用 ECMAScript 6 spread operator,它将尾随参数绑定到一个数组。使用此解决方案,您无需触摸arguments对象,您的代码将得到简化。该解决方案的缺点是它不适用于大多数浏览器,因此您必须使用 JS 编译器,例如 Babel。在引擎盖下,Babel 转换arguments为一个带有 for 循环的数组。

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

如果您不能使用 ECMAScript 6,我建议您查看其他一些答案,例如 @Jonathan Fingland

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}
于 2016-01-25T21:51:50.733 回答
4

使用Array.from(),它将类数组对象(例如arguments)作为参数并将其转换为数组:

(function() {
  console.log(Array.from(arguments));
}(1, 2, 3));

请注意,它不适用于 IE 11 等一些较旧的浏览器,因此如果您想支持这些浏览器,则应使用Babel

于 2016-01-26T09:00:49.357 回答
4

罗达什:

var args = _.toArray(arguments);

在行动:

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

产生:

[2,3]
于 2016-10-04T23:41:17.053 回答
3
function sortArg(){
var args = Array.from(arguments); return args.sort();
}

 function sortArg(){
    var args = Array.from(arguments); 
    return args.sort();
    }
 
 console.log(sortArg('a', 'b', 1, 2, '34', 88, 20, '19', 39, 'd', 'z', 'ak', 'bu', 90));

于 2016-09-11T13:26:00.423 回答
2

这是一个干净简洁的解决方案:

function argsToArray() {
  return Object.values(arguments);
}

// example usage
console.log(
  argsToArray(1, 2, 3, 4, 5)
  .map(arg => arg*11)
);

Object.values( )将返回一个对象的值作为一个数组,并且由于arguments是一个对象,它本质上将转换arguments为一个数组,从而为您提供数组的所有辅助函数,例如map, forEach,filter等。

于 2019-02-12T23:10:43.587 回答
1

另一个答案。

使用黑魔法咒语:

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

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

于 2014-07-10T01:24:28.583 回答
1

尝试使用Object.setPrototypeOf()

解释:prototype一组argumentsArray.prototype

function toArray() {
  return Object.setPrototypeOf(arguments, Array.prototype)
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


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

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

function toArray() {
  return [].map.call(arguments, (_,k,a) => a[k])
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


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

for..of环形

function toArray() {
 let arr = []; for (let prop of arguments) arr.push(prop); return arr
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


或者Object.create()

说明:创建对象,将对象的属性设置为每个索引处的项目arguments;一组prototype创建的对象Array.prototype

function toArray() {
  var obj = {};
  for (var prop in arguments) {
    obj[prop] = {
      value: arguments[prop],
      writable: true,
      enumerable: true,
      configurable: true
    }
  } 
  return Object.create(Array.prototype, obj);
}

console.log(toArray("abc", 123, {def: 456}, [0, [7, [14]]]))

于 2016-01-30T02:11:20.093 回答
0

Benshmarck 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

享受 !

于 2014-07-25T01:02:09.650 回答
0

function sortArgs(...args) {
  return args.sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();

于 2016-01-29T05:47:03.927 回答
0

arguments虽然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()
于 2016-01-30T19:45:10.893 回答
0
 function x(){
   var rest = [...arguments]; console.log(rest);return     
   rest.constructor;
 };
 x(1,2,3)

我尝试了简单的破坏技术

于 2016-07-09T18:17:39.543 回答
0

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

虽然它可以像数组一样被索引,如您在此示例中所见:

function add(){

var sum=0;

for(var i=0; i< arguments.length;i++){

sum = sum + arguments[i];

}

return sum;

}

console.log(add(1,2,3));

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

您可以将 arguments 对象转换为数组,此时您可以访问 Arguments 对象。

您可以通过多种方式访问​​函数体内的参数对象,其中包括:

  1. 你可以调用 Array.prototoype.slice.call 方法。

Array.prototype.slice.call(参数)

function giveMeArgs(arg1,arg2){

var args = Array.prototype.slice.call(arguments);
return args
}

console.log( giveMeArgs(1,2));

  1. 您可以使用数组文字

[].slice.call(参数)。

function giveMeArgs(arg1,arg2){

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

return args;

}

console.log( giveMeArgs(1,2) );

  1. 你可以使用休息...

function giveMeArgs(...args){

return args;

}

console.log(giveMeArgs(1,2))

  1. 您可以使用传播 [...]

function giveMeArgs(){

var args = [...arguments];
return args;

}

console.log(giveMeArgs(1,2));

  1. 你可以使用 Array.from()

function giveMeArgs(){

var args = Array.from(arguments);

return args;

}

console.log(giveMeArgs(1,2));

于 2017-04-22T00:41:32.400 回答
0

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

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

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

扩展语法可以在ES6及更高版本中使用...

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

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

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

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

于 2017-12-24T12:35:36.777 回答
-2

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

function sortArguments() {
  return Array.apply(null, arguments).sort();
}
于 2013-06-18T21:02:23.490 回答