How to remove a specific item from an array in JavaScript
There are two answers, and which one you want depends on a question nobody asks out loud: do you want a new array, or do you want this array changed?
filter or splice
const a = ["a", "b", "c", "b"];
a.filter(x => x !== "b"); // new array
const i = a.indexOf("b");
if (i > -1) a.splice(i, 1); // this array
start : [ 'a', 'b', 'c', 'b' ]
filter !== 'b' : [ 'a', 'c' ] <- removes ALL 'b'
indexOf+splice : [ 'a', 'c', 'b' ] <- removes the FIRST 'b' only
Same input, different results, and neither is wrong.
filter
tests every element, so every match goes.
indexOf
finds one position, so one element goes.
The other difference:
after filter, original : [ 'a', 'b', 'c', 'b' ]
after splice, original : [ 'a', 'c', 'b' ] <- changed
splice
mutates. That matters the moment anyone else holds a reference to the same
array.
The guard is not optional
Leave off the if and the miss case does something specific and bad:
indexOf('zzz') : -1
splice(-1, 1) : [ 'a', 'b', 'c' ] <- removed the LAST item instead of nothing
A negative index counts from the end, so -1 means “the last one”. Searching
for something that is not there deletes a real element — no error, no warning,
and the element it removed is one you never named. Always check > -1.
delete is not it
delete d[1];
after delete d[1] : [ 'a', <1 empty item>, 'c', 'b' ]
length : 4 <- unchanged
1 in d : false
delete
removes the value, not the slot. You are left with a hole, an unchanged
length, and an array that behaves oddly in anything that iterates it.
splice tells you what it took
splice(1, 2) returned: [ 'b', 'c' ] leaving [ 'a', 'b' ]
Second argument is a count, not an end index, and the return value is the removed elements — useful when you want to move something rather than drop it.
By index without mutating
t.toSpliced(1, 1) : [ 'a', 'c', 'b' ] original still [ 'a', 'b', 'c', 'b' ]
typeof Array.prototype.toSpliced : function
toSpliced
is splice that returns a copy. ES2023, so it is in current runtimes but not in
whatever you are asked to support.
Objects compare by identity
filter(o => o !== {id:2}) : 2 items <- nothing removed
filter(o => o.id !== 2) : [ { id: 1 } ]
Two objects with the same contents are not ===. Removing an object either
means comparing a field, or holding the original reference.
Removing while looping forwards skips elements
forwards : [ 'a', 'b', 'c' ] <- one 'b' survived
backwards : [ 'a', 'c' ]
Splicing at index i shifts everything down one, so the next element slides
into the slot the loop has just left. Iterate backwards, or use filter.
And for the ends there is no need for any of this:
pop() : b leaving [ 'a', 'b', 'c' ]
shift() : a leaving [ 'b', 'c' ]
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).