Removing Elements from JavaScript Arrays
The JavaScript standard library is notoriously small. In fact, it is so small that the Array prototype doesn't even define a method for removing a specific element from an array. Because there's no such built-in method, developers have to create their own version if they want to remove a specific array element.
Approach #1: indexOf() and splice() #
A common approach is to combine the indexOf() and splice() methods like this:
function remove(array, element) {
const index = array.indexOf(element);
array.splice(index, 1);
}
First, the index of the element in question is determined via indexOf(). Second, splice() is used to remove the array element at that index. We only want to remove a single value, so we pass 1 as the second argument to splice, which specifies the delete count.
However, our above remove() function is flawed, as a simple example shows:
const vowels = ["a", "e", "i", "o", "u", "x"];
vowels.toString(); // "a,e,i,o,u,x"
// Let's remove "x" since it's not a vowel.
remove(vowels, "x");
vowels.toString(); // "a,e,i,o,u"
// What happens if we remove "x" again? Oops!
remove(vowels, "x");
vowels.toString(); // "a,e,i,o"
The remove() function removes the last array element if the element to remove doesn't occur within the array. In that case, indexOf() returns the sentinel value -1. That value is passed to splice(), which starts to count from the end of the array when it sees a negative index. -1 is the index of the last array element — not what was intended here.
Here's a correct version of the remove() function. The fix is to call splice() if and only if indexOf() didn't return -1:
function remove(array, element) {
const index = array.indexOf(element);
if (index !== -1) {
array.splice(index, 1);
}
}
Look before you leap! Always check your indexOf() return values.
Approach #2: filter() #
Removing an element from a given array is a mutating operation. The remove() function changes the array that was passed to it, which is typically not what the caller would expect.
A better approach would be to implement a non-mutating element removal. Instead of directly modifying the input array, the remove() function could return a new array that contains all elements except the specified one:
function remove(array, element) {
return array.filter(el => el !== element);
}
const vowelsAndX = ["a", "e", "i", "o", "u", "x"];
const vowels = remove(vowelsAndX, "x");
vowels.toString(); // "a,e,i,o,u"
Note that this non-mutating version of remove() works a little differently than its mutating sibling. Instead of removing only the first occurrence of the given element from the new array, we now return a new array that doesn't contain any occurrence of the given element.