如何将“参数”对象转换为JavaScript中的数组?

JavaScript中的对象是一个奇怪的疣 - 在大多数情况下,它就像一个数组,但它实际上并不是一个数组对象。由于它实际上是完全不同的东西,因此它没有Array.prototype中的有用函数,如,,,和。argumentsforEachsortfiltermap

使用简单的 for 循环从参数对象构造新数组非常容易。例如,此函数对其参数进行排序:

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

但是,这是一件相当可怜的事情,只是为了访问非常有用的JavaScript数组函数。有没有一种内置的方法可以使用标准库来做到这一点?


答案 1

使用静止参数的 ES6

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

静止参数

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

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

正如您可以在链接中阅读的那样

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

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

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只需将类似数组或可迭代的对象转换为数组实例即可。



夏令时

你实际上可以在参数对象上使用 的切片函数,它会将其转换为标准的JavaScript数组。您只需要通过Array的原型手动引用它:Array

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

为什么会这样?好吧,以下是 ECMAScript 5 文档本身的摘录:

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

因此,适用于任何具有属性的东西,这很方便。slicelengtharguments


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

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

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


答案 2

还值得参考这个Bluebird承诺的库wiki页面,该页面展示了如何将对象管理到数组中,以使函数在V8 JavaScript引擎下可优化:arguments

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