How to remove element from array

Tuesday 09/08/2022

·5 min read
Share:

Removing an element from a JavaScript array sounds like one operation, but it's actually six different methods depending on where the element is and whether you want to mutate the array. The honest answer: use filter for "remove by condition" and splice for "remove by index." Both are O(n) in the worst case — there's no constant-time removal from the middle of a dense array in JavaScript. Below: every approach, with the gotchas that catch people in code review.

This is the modern default. Non-mutating, predicate-based, chainable:

const arr = [1, 2, 3, 4]
const without3 = arr.filter(x => x !== 3)
// arr is unchanged: [1, 2, 3, 4]
// without3:         [1, 2, 4]

filter returns a new array containing only elements where the predicate is truthy. Use this when you don't care about mutating in place — which is most of the time, especially in React/Vue/Svelte state updates where immutability is required.

For removing by index instead of value:

const withoutIdx1 = arr.filter((_, i) => i !== 1)
// [1, 3, 4]

2. splice — remove by index (mutating)

splice mutates the array and returns the removed elements:

const arr = [1, 2, 3, 4]
const removed = arr.splice(1, 1)
// arr:     [1, 3, 4]
// removed: [2]

Arguments: splice(startIndex, deleteCount, ...itemsToInsert). Use this when you need to both remove and capture what was removed, or when you need in-place mutation (e.g., updating a reactive store that watches the same array reference).

To remove every occurrence of a value, loop from the end:

for (let i = arr.length - 1; i >= 0; i--) {
    if (arr[i] === 3) arr.splice(i, 1)
}

Looping forward and splicing shifts indexes underneath you and causes you to skip elements — a classic bug. Looping backward avoids it.

3. pop — remove the last element

const arr = [1, 2, 3, 4]
const last = arr.pop() // last = 4, arr = [1, 2, 3]

pop mutates and returns the removed element. O(1). This is the right tool for stack-like usage.

4. shift — remove the first element

const arr = [1, 2, 3, 4]
const first = arr.shift() // first = 1, arr = [2, 3, 4]

shift mutates and returns the removed first element. O(n) because every remaining element shifts by one index. For high-throughput queue work, use a linked list or two-stack queue instead.

5. Set length — truncate from the end

const arr = [1, 2, 3, 4]
arr.length = 2 // arr = [1, 2]

Useful when you want to drop the tail of an array in one assignment. Equivalent to arr.splice(2) but slightly faster because it skips the spread/return path. arr.length = 0 is the canonical "empty this array in place" idiom.

6. delete — don't use this

const arr = [1, 2, 3, 4]
delete arr[1] // arr = [1, <empty>, 3, 4], length still 4

delete removes the value but leaves a sparse hole — the array length doesn't change, iteration with map/filter skips the hole, but a plain for loop still hits it as undefined. This is almost always wrong. The only legitimate use is if you specifically want a sparse array, which you don't.

Edge cases and gotchas

  • splice index can be negative. arr.splice(-1, 1) removes the last element — equivalent to pop but wraps the return in an array.
  • filter always allocates a new array even if nothing is removed. For very hot paths, prefer splice to avoid the allocation.
  • Mutation visibility. If multiple parts of your app hold a reference to the same array, splice affects all of them; filter only changes the new reference.
  • pop and shift on empty arrays return undefined — they don't throw. Useful for processing queues until empty.
  • indexOf returns -1 for not-found, and splice(-1, 1) removes the last element. Always guard with if (i >= 0) before splicing by indexOf.

Picking the right method

| Goal | Use | |---|---| | Remove by condition, keep original | filter | | Remove by index, mutate in place | splice | | Remove last element | pop | | Remove first element | shift | | Drop the tail | arr.length = n | | Empty the array | arr.length = 0 |

FAQ

How do I remove a specific element by value?

arr.filter(x => x !== value) for non-mutating removal. To mutate, find the index first and guard against -1: const i = arr.indexOf(value); if (i >= 0) arr.splice(i, 1).

Why doesn't delete arr[i] actually remove the element?

delete removes the value but leaves a sparse slot. The array's length doesn't change, and iteration behavior becomes inconsistent across array methods vs plain loops. Use splice or filter instead.

How do I remove duplicates from an array?

[...new Set(arr)] for primitive values. For objects, use filter with a Set tracking seen identifiers: const seen = new Set(); arr.filter(o => !seen.has(o.id) && seen.add(o.id)).

Does splice modify the array in place?

Yes — splice is one of the few mutating array methods. It returns the removed elements as a new array, but the original is modified. If you need immutability, use filter or toSpliced (ES2023).

Share:
VA

Vadim Alakhverdov

Software developer writing about JavaScript, web development, and developer tools.

Related Posts