Skip to content

A proposal for a new array method to append every element from its argument.

tc39/proposal-bulk-add-array-elements

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Array.prototype.pushAll

This proposal introduces a new method on arrays to push all elements from an iterable onto the end of the array.

Status

Status: Stage 0

Champion: Daniel Rosenwasser (@DanielRosenwasser)

For more information see the TC39 proposal process.

Motivation

Today, the most idiomatic and concise way to append multiple elements to an array from another iterable is to use Array.prototype.push with argument spread syntax (...arg):

const arr = [1, 2, 3];
const newElements = [4, 5, 6];
arr.push(...newElements);

This pattern usually works, but it has some drawbacks. One could argue that this idiom is not entirely obvious or discoverable, especially for developers who are new to JavaScript or unfamiliar with the spread syntax. But the most critical issue with .push(...arg) is the risk of stack overflows when arg is a very large iterable, since the argument spread syntax will expand all elements into individual arguments. This concern is not hypothetical; there have been real-world instances where this has caused runtime errors (for example, see this reported instance from Node.js users).

In these cases, pushing each individual element in a loop or forEach call may be used instead.

for (const item of newElements) {
  arr.push(item);
}

This code is arguably more explicit, but also more verbose for what feels like a common operation. It also may not be optimized ideally in the case where new elements come from another array with a known size. Once enough elements are push-ed, the array's backing storage may need to be resized, and cause intermediate reallocations. Ideally, a runtime could reallocate exactly once if the new element count is known in the case of arrays, and known to exceed the available storage.

Proposed Solution

This proposal suggests adding a new method, Array.prototype.pushAll, which would allow for a more concise and readable way to append all elements from an iterable to an array. The method could (roughly) be polyfillable as follows:

Array.prototype.pushAll = function(iterable) {
  for (const item of iterable) {
    this.push(item);
  }
};

Note

There are some edge cases to consider, such as when the array is modified during the operation (e.g. passing the same target array as its argument). The exact semantics of such cases might involve special-casing array inputs, but could be clarified in later stages.

With this new method, the previous example could be rewritten as:

const arr = [1, 2, 3];
const newElements = [4, 5, 6];
arr.pushAll(newElements);

Existing Precedent

Many other languages have similar methods for appending multiple elements to growable list types. Below is a table that shows how several popular languages handle this operation:

Language Adding a Single Element Adding Multiple Elements
Python items.append(x) items.extend(new_values)
Java items.add(x) items.addAll(newValues)
C# items.Add(x) items.AddRange(newValues)
Ruby items.push(x) items.concat(newValues)
C++ items.push_back(x) items.insert(items.end(), newValues.begin(), newValues.end())
Go items = append(items, x) items = append(items, newValues...)
PHP $array[] = $x $array_push($array, ...$newValues)

About

A proposal for a new array method to append every element from its argument.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks