Array.prototype.push()

The workhorse for building an array. Two things catch people: it returns a number rather than the array, so it cannot be chained, and it mutates.

Array methodES3 (1999)Live demo
Common call
items.push(value)
Returns
number — the new length
Replaces
items[items.length] = value
Watch out
cannot be chained; the return value is a length, not an array
array.push(...items...items — Any number of values, appended in order. Each is added as ONE element, even if it is itself an array.type: any · default: none)
→ number

Demo

Live evaluation
Try:
Inputs
itemsnumber[]starting array, comma separated
valuenumbervalue to append
Output
[1, 2, 3].push(4)
4

Every output here is a NUMBER — the new length after the append, which is what push returns. Pushing onto a three-element array gives 4, not [1, 2, 3, 4]. That is the single most surprising thing about the method, and the reason `const arr = old.push(x)` leaves you holding an integer instead of an array.

Parameters

NameTypeRequiredDescription
...itemsanyno (none)Any number of values, appended in order. Each is added as ONE element, even if it is itself an array.

Return value

number — The NEW length of the array — not the array, and not the pushed element. The array is modified in place.

Common patterns

Build an array in a loop
The standard accumulation pattern.
const out = [];
for (const x of input) out.push(transform(x));
Append several at once
Spread to push the contents of another array.
items.push(...more);
Non-mutating append
When the original must survive — state, props, caches.
const next = [...items, value];

Examples

1. Returns the length
[1, 2].push(3)
Returns
3
2. The array after
const a = [1, 2]; a.push(3); a
Returns
[1, 2, 3]
3. Several at once
const a = [1]; a.push(2, 3)
Returns
3 // the new length
4. Arrays nest
const a = [1]; a.push([2, 3]); a
Returns
[1, [2, 3]]
5. Spread to flatten
const a = [1]; a.push(...[2, 3]); a
Returns
[1, 2, 3]
6. Cannot chain
[1].push(2).push(3)
Returns
TypeError: [1].push(...).push is not a function

Pitfalls

1. It returns the new length, not the array
Assigning the result gives you a number. Because a number is a perfectly valid value, nothing throws at the assignment — the failure appears later when something tries to iterate it.
Got a number
const next = items.push(value);
4
Push, then use
items.push(value);
const next = items;
the array
2. Pushing an array nests it
push adds each argument as one element, so push([1, 2]) appends a single nested array. Spread it when you meant to append its contents.
Nested
const a = [1];
a.push([2, 3]);
a
[1, [2, 3]]
Spread it
a.push(...[2, 3]);
[1, 2, 3]
3. It mutates — bad news for shared arrays
Pushing to a prop, a cached array or a piece of state changes it for everyone holding a reference. In React that means the change is invisible to re-render logic comparing by identity.
Mutates state
state.items.push(x);
same reference, no re-render
New array
setItems([...state.items, x]);
new reference
4. Spreading a huge array can overflow the stack
push(...bigArray) passes every element as a separate argument, and engines cap the argument count somewhere around 100k. On large data it throws rather than degrading.
Too many args
out.push(...hugeArray);
RangeError: Maximum call stack size exceeded
Loop or concat
for (const x of hugeArray) out.push(x);
safe at any size

When to use

Use it
  • Building an array incrementally in a loop
  • Appending to an array you own
  • Stack behaviour, paired with pop
Reach for something else
  • The array is shared or state → [...items, value]
  • You want the array back for chaining → concat or a spread
  • Adding to the FRONT → unshift, though it is O(n)

Notes

Complexity
O(1) amortised per element
Return
A number — the new length; the array is modified in place
CPython impl
V8: Builtins-array-push.tq
Memory
May reallocate the backing store as the array grows
Thread-safe
Single-threaded; mutating a shared array is the hazard here

FAQ

It returns the new length, which dates back to ES3 and is occasionally useful for bookkeeping. It does mean push cannot be chained, and that assigning its result gives you an integer rather than the array you probably wanted.

const len = items.push(x);   // a number

History

ES3
push standardised in 1999 along with pop, shift and unshift.
ES2015
Spread syntax made [...items, value] the idiomatic non-mutating append.