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.