Hi, I have just noticed [1], read all messages on this thread and thought that the "JavaScript stack size limit" for Array.prototype.push.apply(firstArray, secondArray); was an implementation concern rather than anything else and it really sounds weird to me to add a method just because implementations aren't capable of performing well with some methods. Theorically speaking, why .pushAll would do better than .push.apply+second argument? There is no reason I can think of.
I think that implementors did implement strictly ES5 definition of push: Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] ) which considers each item as a new argument, making the stack grow. Why would a .pushAll do better? Because there is only one argument which is an array. So I think that instead of adding pushAll, we'd rather redefine .push with the great "...rest" parameters [2] Array.prototype.push = function(...items){ let O = ToObject(this); let lenVal = O.length; let n = ToUint32(lenVal); let itemsList = ToList(items); // sorry for the bickshed while(itemsList.length != 0){ let E = itemsList.pop(); // bickshed bis O[n] = E; n++; O.length = n; } return n; }; (which is pretty much Jeff's implementation of .pushAll in the initial message) As a matter of fact, maybe that all methods that where previously defined as "myFunction(a, b [, c1 [, c2 [ , … ] ] ])" would have rather being re-specified in the form of "myFunction(a, b, ...c)". Should I file a bug on that? Regarding implementations of .push, if they can do as good as a .pushAll could, then they are just buggy and should be fixed in my opinion. What do you think? David [1] http://wiki.ecmascript.org/doku.php?id=strawman:array.prototype.pushall [2] http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters Le 25/07/2011 21:54, Jeff Walden a écrit : > 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 _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss