Note: this is a cross-post from https://discourse.wicg.io/t/js-array-method-to-append-another-array-in-place/3831
arr1.concat(arr2) returns a new array; this is specifically for an in-place append that modifies
The obvious solution is
arr1.push(...arr2), but this has a nasty gotcha: the spread passes the array as arguments on the stack, which means if
arr2 is long enough, you reach implementation-defined maximum argument length limits. Commonly this is around 65k, but varies from browser to browser. Worse, since the limits are fairly high, writing this type of code at first looks like it works, but then you find out it's broken later on as your arrays get longer and reach limit (worse still, a non-standard limit).
The next obvious solution is to use a loop to call
for (let i = 0, len = arr2.length; i < len; ++i) arr1.push(arr2[i]);
The problem with this is it's significantly slower, to the point we've found a helper method using exactly this approach was coming up high in performance profiles. It makes sense why: the optimizer probably can't tell how long
arr1 will end up, so as it keeps pushing it will have to keep reallocating the backing store to increase the array capacity, and every time it does that it will have to copy the entire array.
arr1.push(...arr2) measurably increased performance - but then we have to impose an arbitrary hard-coded limit on how long
arr2 is to use that fast-path, else fall back to the slow path
push() loop - and then we end up switching to a slow path in the most performance intensive case (with long arrays).
This is all pretty awkward and still doesn't achieve maximum performance with long arrays. It could be solved by adding a new array method, e.g.:
// Appends all of arr2 to the end of arr1 in-place arr1.append(arr2);
This method meets all of the following requirements:
- Modify an existing array, instead of returning a new array
- Resize the backing store once, since the final size is known
- Preserve the internal element kinds (providing the appended array has a compatible internal type)
- Append any size array, without arbitrary/non-standard limits