If I have one array, and I want to append the contents of an arbitrary array to
it, and I don't need the unmodified first array after appending the second
array's elements to it, I have three options.
First, I can use Array.prototype.concat to create a new array consisting of the
first array, then the contents of the second. But this creates a new array
rather than mutating the first array, so it potentially wastes memory
proportional to the size of the first array, barring complicated heuristics to
recognize and avoid the waste. Potentially worse, if any element of the second
array is an Array, instead of that array being appended, its elements will be
appended.
Second, I can use Array.prototype.push:
Array.prototype.push.apply(firstArray, secondArray);
This avoids the memory-wastefulness concern, and it doesn't treat Array items
specially. But it introduces a third concern: the JavaScript stack size limit,
if the second array contains a particularly large number of elements. This
might manifest itself as causing a stack overflow exception, or it might cause
only some of the elements of the second array to be appended (an arguably buggy
mitigation mechanism, but one some engines use, at least currently).
Third, I can use Array.prototype.splice, passing in |start = length| and
|deleteCount = 0|. But splice too encounters the stack size limit problem.
Worse, because its arguments are (start, deleteCount, newElt1, newElt2, ...),
constructing the array of arguments with which to apply the splice method seems
to require complicated copy-on-write array-element-sharing to mutate the first
array without consuming twice the first array's memory, or some other tricky
scheme. For such schemes to be effective here, the programmer would have to
structure his code pretty carefully, being sure to only use
Array.prototype.unshift, say, to implement it. And there's a bootstrapping
problem to creating the array of arguments to supply to splice in order to
append the elements of an array to the first array.
I see no problem-free way to append an array's elements to another array
without doing it manually. That's not hard, but it's error-prone, and it's
much trickier to recognize and correctly optimize. I think there should be a
way to append elements of an arbitrarily sized array to another array, mutating
that array in-place, without consuming excess memory. I'm not too concerned
about its precise semantics or about what it's named. For a starting point
I'll propose Array.prototype.pushAll (or extend, following Python, but again, I
don't really care about the exact name right now):
Object.defineProperty(Array.prototype, "pushAll",
{
enumerable: false, configurable: true, writable: true,
value: function pushAll(other)
{
"use strict";
var t = ToObject(this);
var length = ToUint32(t.length);
var otherLen = other.length;
for (var i = 0, j = length; i < otherLen; i++, j++)
t[j] = other[i];
t.length = j;
return void 0;
},
});
Comments? Suggestions? Requests for changes?
I also had the thought that it might be nice to be able to push a subrange of
the elements of an array. You could do that by adding optional |start, length|
or |start, end| arguments to the method, with corresponding implementation
changes. I'm not sure whether this would be useful enough to warrant the
complexity, but it would be easy to add if people thought it made sense.
Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss