Array.prototype.append ?

# Jordi Bunster (6 years ago)

Has anyone ever suggested Array.prototype.append as an Array.prototype.push which returns the array itself? It would be reduce-friendly, same as Set.prototype.add and Map.prototype.set.

Someone has to have, right? 😊

# Jordi Bunster (6 years ago)

Cool!

So for me, the point would be symmetry with Map and Set.

As such my poly would go like so:

Object.defineProperty(Array.prototype, "append", {
    writable: true,
    configurable: true,
    value: function(arg) {
        this.push(arg);
        return this;
    }
});

(Which is basically what I end up doing with && in a => in reduce() calls...)

# T.J. Crowder (6 years ago)

On Wed, May 23, 2018 at 6:49 PM, Jordi Bunster <jbunster at microsoft.com>

wrote:

Cool!

So for me, the point would be symmetry with Map and Set.

Are you saying you'd want to have append on them as well?

As such my poly would go like so:

Object.defineProperty(Array.prototype, "append", {
    writable: true,
    configurable: true,
    value: function(arg) {
        this.push(arg);
        return this;
    }
});

For some reason, in my head you were calling append with an array, not discrete items. Not sure why that was. Silly of me. I've rarely needed an append for individual items, my use cases have generally been appending an array to another array. But that could be its own separate thing (appendArray). (I wouldn't overload it as with concat.)

I'd lean toward accepting as many as are given, as with push:

Object.defineProperty(Array.prototype, "append", {
    value: function(...items) {
        for (let i = 0, len = source.length; i < len; ++i) {
            this.push(item[i]);
        }
        return this;
    },
    writable: true,
    configurable: true
});

-- T.J. Crowder

# Isiah Meadows (6 years ago)

Since Array.prototype.push is variadic, I don't see how this would be any improvement on the status quo (which isn't that bad to begin with).

# T.J. Crowder (6 years ago)

On Wed, May 23, 2018 at 11:06 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

Since Array.prototype.push is variadic, I don't see how this would be any improvement on the status quo (which isn't that bad to begin with).

On Wed, May 23, 2018 at 9:14 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Wed, May 23, 2018 at 1:05 PM, Jordan Harband <ljharb at gmail.com> wrote:

array.push(...sources), not sure why we'd need "append".

From the original email (a bit buried and hard to find due to broken threading, admittedly):

Has anyone ever suggested Array.prototype.append as an Array.prototype.push which returns the array itself?

The point is x.append(y) returning x, whereas x.push(y) returns y.

With large arrays you can also run into a platform's stack size limit with a large number of arguments. I got curious, and unless my test is significantly flawed, that limit is definitely a factor. The test uses dest.push.apply(dest, source) and works in chunks of 10k entries, reporting the point at which it got a stack error:

  • Chrome v66: Between 120k and 130k entries
  • Firefox v60: 500k - 510k
  • Edge v41: 650k - 660k
  • IE11: 250k - 260k
  • IE8¹: 5.25M (!) - 5.26M

Using dest.push(...source) instead gave the same numbers as above on Chrome, Firefox, and Edge.

So two reasons: Returning the array, and not pushing (no pun) the limit. ~125k entries isn't all that many.

-- T.J. Crowder

¹ Hey, some people still have to support it (e.g., via transpilation) -- old embedded IE-based apps in large institutions, etc. I'm just glad not to be one of them.

# Andrea Giammarchi (6 years ago)

I remember doing similar benchmarks for String.fromCharCode with a wrap of the native function that was splitting invokes in chunks of 2K chars MAX per operation ... but I think the arguments limits, which is the same you have in push is a JS issue as a whole, not something array specific.

As side note, append(...items) { return this.push(...[...items]), this; } would be equivalent, but you could also write this without needing to add yet another method to the Array: (array.push(...items), array) looks easy to my eyes, nothing new to learn.

My 2 cents

# Isiah Meadows (6 years ago)

Some responses to these, inline.


Isiah Meadows me at isiahmeadows.com, www.isiahmeadows.com

On Thu, May 24, 2018 at 3:33 AM, T.J. Crowder <tj.crowder at farsightsoftware.com> wrote:

On Wed, May 23, 2018 at 11:06 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

Since Array.prototype.push is variadic, I don't see how this would be any improvement on the status quo (which isn't that bad to begin with).

On Wed, May 23, 2018 at 9:14 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Wed, May 23, 2018 at 1:05 PM, Jordan Harband <ljharb at gmail.com> wrote:

array.push(...sources), not sure why we'd need "append".

From the original email (a bit buried and hard to find due to broken threading, admittedly):

Has anyone ever suggested Array.prototype.append as an Array.prototype.push which returns the array itself?

The point is x.append(y) returning x, whereas x.push(y) returns y.

@Jordan, x.push(y) returns x.length (specifically, the new length).

With large arrays you can also run into a platform's stack size limit with a large number of arguments. I got curious, and unless my test is significantly flawed, that limit is definitely a factor. The test uses dest.push.apply(dest, source) and works in chunks of 10k entries, reporting the point at which it got a stack error:

  • Chrome v66: Between 120k and 130k entries
  • Firefox v60: 500k - 510k
  • Edge v41: 650k - 660k
  • IE11: 250k - 260k
  • IE8¹: 5.25M (!) - 5.26M

Wait, what? Of all things old IE screws up, this isn't one of them?

Using dest.push(...source) [instead][2] gave the same numbers as above on Chrome, Firefox, and Edge.

So two reasons: Returning the array, and not pushing (no pun) the limit. ~125k entries isn't all that many.

Was the proposal for (const i of y) x.push(y), like a mutable concat? I interpreted it as basically x.push(y); return x from the start, hence why I didn't see the point.

Adding a mutable concat variant would be useful, though, enough that I'd like to see it happen. Add an optional mapping callback like with Array.from, and I'd be set. But in this case, I'd rather it be named Array.prototype.pushAll, not Array.prototype.append. 1

# T.J. Crowder (6 years ago)

On Thu, May 24, 2018 at 7:02 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

With large arrays you can also run into a platform's stack size limit with a large number of arguments. [snip]

  • Chrome v66: Between 120k and 130k entries
  • Firefox v60: 500k - 510k
  • Edge v41: 650k - 660k
  • IE11: 250k - 260k
  • IE8¹: 5.25M (!) - 5.26M

Wait, what? Of all things old IE screws up, this isn't one of them?

I know, right?

Was the proposal for (const i of y) x.push(y), like a mutable concat? I interpreted it as basically x.push(y); return x from the start, hence why I didn't see the point.

Sorry, that's my bad. The original from Jordi Bunster was indeed just x.push(y); return x:

Has anyone ever suggested Array.prototype.append as an Array.prototype.push which returns the array itself? It would be reduce-friendly, same as Set.prototype.add and Map.prototype.set.

Someone has to have, right? 😊

Somehow in my head it became a mutating verson of concat, possibly because I've often wanted a mutating version of concat, but I don't recall really wanting a version of push that returns the array.

pushAll looks good to me. (Re the desugared code: You don't need that this.length = index at the end, though. :-) )

-- T.J. Crowder

# Isiah Meadows (6 years ago)

Yes, I do need that. If you look at the implementation, it makes no attempt to set it prior, and I designed it to work generically just like how Array.prototype.push does now (see step 7). I'm aware that if you assume it's an array, the length will update itself, but it won't on array-likes.


Isiah Meadows me at isiahmeadows.com, www.isiahmeadows.com

# T.J. Crowder (6 years ago)

On Fri, May 25, 2018 at 1:58 PM, Isiah Meadows <isiahmeadows at gmail.com>

wrote:

I'm aware that if you assume it's an array, the length will update itself, but it won't on array-likes.

Ah, fair enough, supporting array-likes.

-- T.J. Crowder