There doesn't seem to be a way to extend an existing JavaScript array with another array, i.e. to emulate Python's extend
method.
I want to achieve the following:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
I know there's a a.concat(b)
method, but it creates a new array instead of simply extending the first one. I'd like an algorithm that works efficiently when a
is significantly larger than b
(i.e. one that does not copy a
).
Note: This is not a duplicate of How to append something to an array? -- the goal here is to add the whole contents of one array to the other, and to do it "in place", i.e. without copying all elements of the extended array.
You should use a loop-based technique. Other answers on this page that are based on using
.apply
can fail for large arrays.A fairly terse loop-based implementation is:
You can then do the following:
DzinX's answer (using push.apply) and other
.apply
based methods fail when the array that we are appending is large (tests show that for me large is > 150,000 entries approx in Chrome, and > 500,000 entries in Firefox). You can see this error occurring in this jsperf.An error occurs because the call stack size is exceeded when 'Function.prototype.apply' is called with a large array as the second argument. (MDN has a note on the dangers of exceeding call stack size using Function.prototype.apply - see the section titled "apply and built-in functions".)
For a speed comparison with other answers on this page, check out this jsperf (thanks to EaterOfCode). The loop-based implementation is similar in speed to using
Array.push.apply
, but tends to be a little slower thanArray.slice.apply
.Interestingly, if the array you are appending is sparse, the
forEach
based method above can take advantage of the sparsity and outperform the.apply
based methods; check out this jsperf if you want to test this for yourself.By the way, do not be tempted (as I was!) to further shorten the forEach implementation to:
because this produces garbage results! Why? Because
Array.prototype.forEach
provides three arguments to the function it calls - these are: (element_value, element_index, source_array). All of these will be pushed onto your first array for every iteration offorEach
if you use "forEach(this.push, this)"!You can create a polyfill for extend as I have below. It will add to the array; in-place and return itself, so that you can chain other methods.
Combining the answers...
If you want to use jQuery, there is $.merge()
Example:
Result: a =
[1, 2, 3, 4, 5]
It is possible to do it using
splice()
:But despite being uglier it is not faster than
push.apply
, at least not in Firefox 3.0.I like the
a.push.apply(a, b)
method described above, and if you want you can always create a library function like this:and use it like this