Array.prototype.splice()

The one Array method that both mutates and returns something surprising. The demo below shows the return value: the elements taken OUT, not the array left behind.

Array methodES3 (1999)Live demo
Common call
items.splice(i, 1)
Returns
the REMOVED elements, as an array
Replaces
nothing; toSpliced() is the non-mutating version
Watch out
the return value is not the array — read the original to see the result
array.splice(start[, deleteCount[, ...items]])
→ Array

Demo

Live evaluation
Try:
Inputs
itemsnumber[]numbers, comma separated
startnumberstart index
countnumberhow many to remove
Output
[1, 2, 3, 4, 5].splice(1, 2)
[2, 3]

Every output here is the list of elements REMOVED — that is what splice returns. Removing two from index 1 of [1,2,3,4,5] gives [2, 3] back, and leaves the original as [1, 4, 5], which the demo cannot show because the return value is all you get. A count of 0 removes nothing and returns an empty array, which is how you insert without deleting. A count past the end simply stops rather than erroring.

Parameters

NameTypeRequiredDescription
startnumberyesIndex to begin changing at. Negative counts from the end. Beyond the length appends.
deleteCountnumberno (to the end)How many elements to remove. Zero removes nothing, which is how you insert without deleting. Omitted entirely, everything from start onward is removed.
...itemsanyno (none)Elements to insert at start, after the removal. Any number of them.

Return value

Array — An array of the REMOVED elements — not the modified array. Empty when nothing was removed. The original array is modified in place.

Common patterns

Remove one element by index
The most common use by far.
items.splice(index, 1);
Insert without removing
A deleteCount of 0 makes splice a pure insert.
items.splice(2, 0, 'new');
Replace in place
Remove and insert in a single call.
items.splice(1, 2, 'a', 'b');

Examples

1. Returns the removed
[1, 2, 3, 4, 5].splice(1, 2)
Returns
[2, 3]
2. The array after
const a = [1, 2, 3, 4]; a.splice(1, 2); a
Returns
[1, 4]
3. Remove nothing
[1, 2, 3].splice(0, 0)
Returns
[]
4. Count past the end
[1, 2, 3].splice(1, 99)
Returns
[2, 3]
5. Negative start
[1, 2, 3].splice(-2, 1)
Returns
[2]
6. Non-mutating version
[1, 2, 3, 4].toSpliced(1, 2)
Returns
[1, 4] // ES2023

Pitfalls

1. It returns the removed elements, not the array
The defining confusion. Assigning the result gives you the discarded elements, and the array you actually wanted is the original — which has already been modified underneath you.
Got the wrong thing
const a = [1, 2, 3, 4];
const result = a.splice(1, 2);
result
[2, 3] // the removed ones
Read the original
a.splice(1, 2);
a
[1, 4]
2. It mutates — including shared arrays
splice edits the array in place, so props, cached values and anything else holding a reference all see the change. This is what makes it dangerous in React state and similar.
Mutates the prop
props.items.splice(0, 1);
the parent's array changed
Copy or filter
const next = props.items.filter((_, i) => i !== 0);
the original is untouched
3. Splicing inside a loop skips elements
Removing an element shifts everything after it down one, while the loop index still moves up — so the element immediately after each removal is never visited.
Skips neighbours
for (let i = 0; i < a.length; i++)
  if (bad(a[i])) a.splice(i, 1);
consecutive bad items survive
Filter instead
a = a.filter(x => !bad(x));
all removed
4. Omitting deleteCount removes everything after start
splice(1) is not "remove one at index 1" — it is "remove from index 1 to the end". The missing second argument changes the meaning completely.
Removes the tail
[1, 2, 3, 4].splice(1)
[2, 3, 4]
Say how many
[1, 2, 3, 4].splice(1, 1)
[2]

When to use

Use it
  • Removing an element by index from an array you own
  • Inserting at a position with deleteCount 0
  • Replacing a run of elements in one call
Reach for something else
  • The array is shared or a prop → filter, or toSpliced
  • You only want a copy of a range → slice
  • You are removing inside a loop → filter
  • You need the resulting array as the return value → toSpliced

Notes

Complexity
O(n) — elements after the splice point shift
Return
A new array of the removed elements; the source is modified in place
CPython impl
V8: Builtins-array-splice.tq
Memory
Allocates the removed-elements array; the source is resized in place
Thread-safe
Single-threaded; mutating a shared array is the usual hazard here

FAQ

It returns what it REMOVED, which is by design — that is how you capture the elements you just cut out. The modified array is the original; splice has already changed it in place, so just read the variable you called it on.

const a = [1, 2, 3, 4];
const removed = a.splice(1, 2);
removed;  // [2, 3]
a;        // [1, 4]

History

ES3
splice standardised in 1999 with the remove-and-insert signature.
ES2023
toSpliced added — the non-mutating counterpart that returns the resulting array.