如何在JavaScript中将"arguments"对象转换为数组?

And*_*son 424 javascript arrays sorting arguments variadic-functions

argumentsJavaScript中的对象是一个奇怪的疣 - 它在大多数情况下就像一个数组,但它实际上并不是一个数组对象.因为它是真正的完全是另一回事,它没有从有用的功能Array.prototype类似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();
}
Run Code Online (Sandbox Code Playgroud)

但是,这是一个相当可怜的事情,只需要访问非常有用的JavaScript数组函数.是否有使用标准库的内置方法?

Jon*_*and 704

ES6使用休息参数

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

休息参数

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

document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
Run Code Online (Sandbox Code Playgroud)

正如您可以在链接中阅读

rest参数语法允许我们将无限数量的参数表示为数组.

如果您对...语法感到好奇,可以将其称为Spread Operator,您可以在这里阅读更多内容.

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();
Run Code Online (Sandbox Code Playgroud)

Array.from 只需将Array-like或Iterable对象转换为Array实例.



ES5

实际上,你可以只使用Arrayslice功能上的参数对象,这将其转换成一个标准的JavaScript数组.你只需要通过Array的原型手动引用它:

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}
Run Code Online (Sandbox Code Playgroud)

为什么这样做?那么,这是ECMAScript 5文档本身的摘录:

注意:该slice功能是故意通用的; 它不要求它的这个值是一个Array对象.因此,它可以转移到其他类型的对象以用作方法.slice函数是否可以成功应用于宿主对象取决于实现.

因此,slice适用于任何具有length属性的东西,这arguments很方便.


如果Array.prototype.slice对你来说太过满口,可以使用数组文字略微缩写:

var args = [].slice.call(arguments);
Run Code Online (Sandbox Code Playgroud)

但是,我倾向于认为前一个版本更明确,所以我更喜欢它.滥用数组文字符号感觉很乱,看起来很奇怪.

  • "你不应该对参数进行切片,因为它会阻止JavaScript引擎中的优化(例如V8)." - 来自MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments (16认同)
  • 什么是'0`?由于你没有想要传递的参数,为什么不能只使用`var args = Array.prototype.slice.call(arguments);`?[**MDC参数页面**](https://developer.mozilla.org/en/JavaScript/Reference/functions_and_function_scope/arguments)建议不带"0"的方法. (9认同)
  • 在最近的Firefox版本(2.0?)和ECMAScript 5中,有一个Array.slice方法可以使它更简单一些.你可以这样称它:var arge = Array.slice(arguments,0);. (5认同)
  • @Barney - 排序是必要的,因为原始问题想要对参数进行排序.如果您只想将其转换为数组,则没有必要. (3认同)
  • 我不确定是否回答了原来的问题.时间流逝了.通过在Firefox和Chrome中进行ES6实验,_rest参数_正在成为一个很好的选择 - "function sortArgs(... argsToSort){return argsToSort.sort(); 来自MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters (3认同)
  • 通过`slice()`将类似数组的对象转换为数组,遗憾的是,不能在浏览器中可靠地工作 - 例如,IE无法以这种方式转换节点列表; 对于适用于所有类似数组的对象的通用函数,无法手动循环条目 (2认同)

jbm*_*sso 40

还值得参考这个Bluebird promises库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;
}
Run Code Online (Sandbox Code Playgroud)

这种方法有利于使用var args = [].slice.call(arguments);.作者还展示了构建步骤如何帮助减少冗长.

  • +1并感谢Bluebird Optimization Killer页面的链接.PS:我最近在[node-thunkify](https://github.com/tj/node-thunkify/commit/d537460eb23e3d556c4f726eb04bef189dd3994f)项目中看到了这种优化. (2认同)

mat*_*tyr 29

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

// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
Run Code Online (Sandbox Code Playgroud)

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

[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
Run Code Online (Sandbox Code Playgroud)


Lig*_*awa 12

使用:

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

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

Array(str1) 回报 [str1]

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

你必须检查参数的数量!

Array.slice 版本(较慢):

function sortArguments() {
  return Array.prototype.slice.call(arguments).sort();
}
Run Code Online (Sandbox Code Playgroud)

Array.push 版本(比切片慢,速度快):

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

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

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

Array.concat 版本(最慢):

function sortArguments() {
  return Array.prototype.concat.apply([], arguments).sort();
}
Run Code Online (Sandbox Code Playgroud)


bra*_*rad 9

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

function sortArgs(){
  return $.makeArray(arguments).sort();
}
Run Code Online (Sandbox Code Playgroud)

  • "除非还包含框架/库的另一个标签,否则需要纯JavaScript答案." (2认同)

Mic*_*ski 6

在ECMAScript 6中,无需使用丑陋的hack Array.prototype.slice()。您可以改为使用传播语法(...

(function() {
  console.log([...arguments]);
}(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)

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

console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);
Run Code Online (Sandbox Code Playgroud)

请注意,它在某些较旧的浏览器(如IE 11)中不起作用,因此,如果要支持这些浏览器,则应使用Babel


小智 5

以下是将参数转换为数组的几种方法的基准.

至于我,少量参数的最佳解决方案是:

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

对于其他情况:

function sortArgs (){ return Array.apply(null, arguments).sort(); }
Run Code Online (Sandbox Code Playgroud)


Mys*_*cal 5

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

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

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

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