argument 转换成 Array的方式
发布于 10 年前 作者 fengmk2 6839 次浏览 最后一次编辑是 6 年前

node源代码中基本是 Array.prototype.slice.call(arguments) 的方式,不过做了一下benchmark,还是最原始的方式最快,不知道大家又是使用什么方式的呢?

var Benchmark = require('benchmark');

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

function forAndArrayPush() {
  var args = [];
  for (var i = 0, l = arguments.length; i < l; i++) {
    args.push(arguments[i]);
  }
  return args;
}

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

var suite = new Benchmark.Suite();

suite
.add('slice()', function () {
  slice(1, 2, 3, 4, 5);
})
.add('forAndArrayPush()', function () {
  forAndArrayPust(1, 2, 3, 4, 5);
})
.add('forAndArraySet()', function () {
  forAndArraySet(1, 2, 3, 4, 5);
})
// add listeners
.on('cycle', function (event, bench) {
  console.log(String(bench));
})
.on('complete', function () {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({ async: true });

测试结果:

$ node argument2array.js 
slice() x 3,620,855 ops/sec ±6.12% (79 runs sampled)
forAndArrayPust() x 5,377,382 ops/sec ±5.86% (78 runs sampled)
forAndArraySet() x 3,542,476 ops/sec ±3.88% (82 runs sampled)
Fastest is forAndArrayPust()

大家可以到 jsperf 上亲自测试一下: arguments to Array

8 回复

基本上用的是 Array.prototype.slice.call(arguments) 这种方式
比较直接方便,不过牺牲了性能

此方法与Array.prototype.slice 一致:

function slice2() {
  return [].slice.call(arguments);
}

测试结果

slice(1, 2, 3, 4, 5) x 3,924,823 ops/sec ±2.34% (91 runs sampled)
slice2(1, 2, 3, 4, 5) x 3,973,870 ops/sec ±0.85% (94 runs sampled)
forAndArrayPust(1, 2, 3, 4, 5) x 5,849,573 ops/sec ±1.14% (88 runs sampled)
forAndArraySet(1, 2, 3, 4, 5) x 4,171,946 ops/sec ±3.98% (85 runs sampled)

既然你只是想转换为数组,可以用下法

Array.apply([], arguments)

用你这个方法最方便

var __slice = Array.prototype.slice

function slice3(){
  return __slice.call(arguments);
}

刚看到jsperf上别人提交的新方法: 10x http://jsperf.com/arguments-to-array/5

function newArrayArgumentsLength() {
  var args = new Array(arguments.length);
  for (var i = 0, l = arguments.length; i < l; i++) {
    args[i] = arguments[i];
  }
  return args;
}

@suqian

slice(1, 2, 3, 4, 5) x 5,036,869 ops/sec ±0.94% (81 runs sampled)
slice2(1, 2, 3, 4, 5) x 5,030,818 ops/sec ±0.74% (88 runs sampled)
forAndArrayPust(1, 2, 3, 4, 5) x 5,116,739 ops/sec ±0.66% (83 runs sampled)
forAndArraySet(1, 2, 3, 4, 5) x 2,955,529 ops/sec ±0.50% (79 runs sampled)
newArrayArgumentsLength(1, 2, 3, 4, 5) x 16,990,646 ops/sec ±1.12% (90 runs sampled)
Fastest is newArrayArgumentsLength(1, 2, 3, 4, 5)
回到顶部