Mörre Noseshine Mörre Noseshine - 2 months ago 32
Javascript Question

Why is [].concat() fast than Array.prototype.concat()?

I tested various array concatenation techniques not because it actually matters to my code but merely as an aside, to see where we are right now. As expected the very new ES 2015 spread operator is beaten by the old

concat()
method on Javascript arrays by a considerable margin.

However, what surprised me a bit was when I compared these two:



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

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

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





I tested, and ran multiple times before doing the next one, on the latest node.js, Chrome and Edge browsers. With V8 (node.js, Chrome) the result is even bigger, but even for Edge the first option is always clearly - on V8 significantly - slower than the second option.

So I'm asking merely out of curiosity, since I did not foresee this at all,

1) Apart from performance, is there any practical difference between the two ways to concatenate those arrays?

2) Why is the one that AFAICS creates one object (array) less than the other (the initial array) slower?

Edit: I know the methods are the same, that's why I tested the direct access to the method on the prototype instead of creating an (unused) array object to access it.

Answer

Array.prototype.concat needs to be resolved in every loop. If you would lookup the function only once, you'll see different results. This may vary depending on the implementation of the runtime though.

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

To get more accurate results, use a proper benchmarking library (eliminates warm up time for example).