为什么[] .concat()比Array.prototype.concat()快?

时间:2016-09-15 13:07:40

标签: javascript performance

我测试了各种数组连接技术,不是因为它对我的代码实际上很重要,而仅仅是为了看看我们现在的位置。正如预期的那样,新的ES 2015传播运营商在Javascript阵列上被旧的concat()方法击败了相当大的差距。

但是,当我比较这两个时,让我感到惊讶的是:



var a = b = c = [1,2,3,4,5];

// SLOWER (V8 and Edge, very slightly faster in Firefox)
console.time('t1');
for (i = 0; i < 1000000; i++) {
  Array.prototype.concat(a, b, c);
};
console.timeEnd('t1')

// FASTER (V8 and Edge, very slightly slower in Firefox)
console.time('t2');
for (i = 0; i < 1000000; i++) {
  [].concat(a, b, c);
};
console.timeEnd('t2')
&#13;
&#13;
&#13;

我在最新的node.js,Chrome和Edge浏览器上测试并运行了多次,然后再运行下一次。使用V8(node.js,Chrome),结果甚至更大,但即使对于Edge,第一个选项总是很明显 - 在V8上显着 - 比第二个选项慢。在Firefox中,结果反转但几乎相同,所以让我们将问题限制在另外两个浏览器引擎(V8和Chakra)。

所以我只是出于好奇而问,因为我根本没有预见到这一点,

1)除了性能之外,连接这些数组的两种方法之间是否存在实际差异?

2)为什么AFAICS创建一个对象(数组)的数量少于另一个(初始数组)更慢

编辑:我知道方法是相同的,这就是为什么我测试了对原型上方法的直接访问,而不是创建一个(未使用的)数组对象来访问它。我也知道它依赖于浏览器,这是a)为什么我测试了两个基于V8的系统(Chrome和node.js)和Microsoft Edge浏览器,以及b)为什么我包含了上面的可运行测试用例。

顺便说一句,这个问题得到了4个downvotes和一个&#34; close:太宽泛&#34;在发布之后仅在(!)内投票。我想非常绝望地请求您花时间实际阅读问题,并在转到投票按钮之前考虑它们超过2秒钟。最初的批评都没有证明是正确的。我出于某种目的包含了一个可运行的例子。

2 个答案:

答案 0 :(得分:7)

Array.prototype.concat需要在每个循环中解决。如果您只查找一次该功能,您会看到不同的结果。这可能会因运行时的实现而有所不同。

&#13;
&#13;
var a = b = c = [1,2,3,4,5];

// Array.prototype.concat
console.time('t1');
var apc = Array.prototype.concat;
for (i = 0; i < 1000000; i++) {
  apc.call([], a, b, c);
};
console.timeEnd('t1')

// [].concat
console.time('t2');
for (i = 0; i < 1000000; i++) {
  [].concat(a, b, c);
};
console.timeEnd('t2')

// They're the same:
console.log(Array.prototype.concat === [].concat);
&#13;
&#13;
&#13;

要获得更准确的结果,请使用适当的基准测试库(例如,消除预热时间)。

答案 1 :(得分:0)

接受的答案不正确。在Chromium中,以下代码显示执行差异与外部查找无关,而与上下文有关,即this内部{{1} }。 (在Firefox中,concat()的优势很小,甚至不一致。)

[].concat()情况下,上下文是一个空数组,其元素将包含在串联结果中。对于[].concat(),上下文是Array.prototype.concat(),它也是一个数组,在“ array-sense”中也为“空”,但充满了方法...我不确定为什么< / em>就是这样。

更新:我正在玩一个自定义数组:一个数组包含许多非数字成员,即length ===0。与空数组相比,它花费了两倍的时间,但仍不及{{1 }} ...

Array.prototype