How to remove element from array
Tuesday 09/08/2022
·5 min readRemoving 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.
1. filter — remove by condition (recommended)
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
spliceindex can be negative.arr.splice(-1, 1)removes the last element — equivalent topopbut wraps the return in an array.filteralways allocates a new array even if nothing is removed. For very hot paths, preferspliceto avoid the allocation.- Mutation visibility. If multiple parts of your app hold a reference to the same array,
spliceaffects all of them;filteronly changes the new reference. popandshifton empty arrays returnundefined— they don't throw. Useful for processing queues until empty.indexOfreturns -1 for not-found, andsplice(-1, 1)removes the last element. Always guard withif (i >= 0)before splicing byindexOf.
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).