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

IT技术 javascript arrays sorting arguments variadic-functions
2021-02-01 02:52:49

argumentsJavaScript 中对象是一个奇怪的疣——它在大多数情况下就像一个数组,但它实际上不是一个数组对象。因为它是真正的完全是另一回事,它没有从有用的功能Array.prototype类似forEachsortfilter,和map

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

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

然而,仅仅为了访问非常有用的JavaScript数组函数而不得不这样做是一件相当可怜的事情。是否有使用标准库的内置方法?

6个回答

ES6 使用 rest 参数

如果您能够使用 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-like 或 Iterable 对象转换为 Array 实例。



ES5

实际上,您可以在参数对象上使用Array'sslice函数,它会将其转换为标准的 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);

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

在最近的 Firefox 版本 (2.0?) 和 ECMAScript 5 中,有一个 Array.slice 方法使这更简单一些。你可以这样称呼它:var arge = Array.slice(arguments, 0);。
2021-03-12 02:52:49
@Barney - 排序是必要的,因为原始问题想要对参数进行排序。如果只是想将其转换为数组,则没有必要。
2021-03-31 02:52:49
有什么0用?既然没有要传递的参数,为什么不直接使用var args = Array.prototype.slice.call(arguments);[ MDC 参数页面]( developer.mozilla.org/en/JavaScript/Reference/... ) 建议使用不带0.
2021-04-06 02:52:49
我不确定这是对原始问题的回答。时间过去了。随着 ES6 在 Firefox 和 Chrome 中的试验,rest 参数正在成为一个很好的选择——function sortArgs(...argsToSort) { return argsToSort.sort(); }来自 MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-09 02:52:49
“你不应该对参数进行切片,因为它会阻止 JavaScript 引擎(例如 V8)的优化。” - 来自 MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-11 02:52:49

还值得参考这个 Bluebird Promise库 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);. 作者还展示了构建步骤如何帮助减少冗长。

+1 并感谢您提供 Bluebird Optimization Killer 页面的链接。PS:我最近在node-thunkify项目中看到了这种优化
2021-03-27 02:52:49
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})

利用:

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 版本(比切片更慢,更快):

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();
}
请注意,由于 Array.concat 中的扁平化行为,它将接受数组参数。sortArguments(2,[3,0],1) 返回 0,1,2,3。
2021-03-30 02:52:49

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

function sortArgs(){
  return $.makeArray(arguments).sort();
}
“除非还包括框架/库的另一个标签,否则纯 JavaScript 答案是预期的。”
2021-03-31 02:52:49
这基本上是我在纯 JS 中寻找的内容,但是对于 jQuery 如何使 JS 更容易理解的可靠示例,+1。
2021-04-07 02:52:49