For AI agents: the complete documentation index is available at /tc39-atlas/en/llms.txt, the full documentation bundle is available at /tc39-atlas/en/llms-full.txt, and this page is available as Markdown at /tc39-atlas/en/proposals/proposal-bulk-add-array-elements.md.
  • English
  • Bulk-add array elements S1

    Proposal details
    Proposal overview

    This proposal introduces Array.prototype.pushAll to append all elements from an iterable to an array, addressing the verbosity and stack overflow risks of spread syntax in push calls.

    Note

    The README below comes from the upstream repository and may contain outdated stage or status metadata. Use the proposal details above as the current source of truth.

    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: