Javascript Array Filter Method

Johnny Simpson - Oct 17 '22 - - Dev Community

The filter method in Javascript creates a shallow copy of an array, filtering it based on a number of conditions. It accepts a callback function. The array which filter produces will usually be a reduced version of the original array. Here is a basic example:

let myArray = [ '⚡️', '🔎', '🔑', '🔩' ];
let filteredArray = myArray.filter((element) => {
    return (element == '🔑' || element == '🔩'))
});

console.log(filteredArray); // [ '🔑', '🔩' ]
Enter fullscreen mode Exit fullscreen mode

As you can see, the filter method will allow an element to be in the new, filtered array, should that element return true. It effectively loops through each element, and runs a test on it, to see what should be left. Since arrow functions return true implicitly on a single line, you might see a more reduced version of this code written like this:

let myArray = [ '⚡️', '🔎', '🔑', '🔩' ];
let filteredArray = myArray.filter(element => element == '🔑' || element == '🔩');

console.log(filteredArray); // [ '🔑', '🔩' ]
Enter fullscreen mode Exit fullscreen mode

The filter method callback function

As mentioned, filter accepts a callback function. The callback function consists of 3 arguments:

Array.filter((element, index, array) => {
    // Filter the array
});
Enter fullscreen mode Exit fullscreen mode

Let's look at what each of these do

element

This is the current element being examined by filter. filter goes through each item in the array to test if it should exist in the new, filtered array.

index

This is the zero based index of the array item we are working with. For example, if we were viewing the first element in the array, this would be 0.

array

This is the entire array, should you wish to do something with the original array.

Mutating arrays within the filter method

Since filter uses a callback function, it is possible to mutate the original array we are examining. For example, we could push new items to the array each time we filter over an item:

let myArray = [ '⚡️', '🔎', '🔑', '🔩' ];
let filteredArray = myArray.filter((element) => {
    myArray.push('⚡️');
    return true;
});

console.log(filteredArray); // [ '⚡️', '🔎', '🔑', '🔩' ]
Enter fullscreen mode Exit fullscreen mode

As you might have already realised, this would produce an infinite loop. Fortunately, much like in reduce, Javascript does not allow this to happen - instead, any new elements to an array added in this way are ignored. However, mutation of existing elements is totally fine:

let myArray = [ '⚡️', '🔎', '🔑', '🔩' ];
let filteredArray = myArray.filter((element, index) => {
    myArray[index + 1] = '⚡️';
    return (element == '⚡️');
});

console.log(filteredArray); // [ '⚡️', '⚡️', '⚡️', '⚡️' ]
Enter fullscreen mode Exit fullscreen mode

Filtering Arrays of Objects

Filtering arrays of objects follows the same conventions as with arrays. We can filter upon child properties of objects within an array by using the . notation. For example, if I wanted to filter the following array by age, where age should be >18, I would do something like this:

let myArray = [ { age: 4 }, { age: 12 }, { age: 19 }, { age: 21 } ];
let filteredArray = myArray.filter((element, index) => {
    return (element.age > 18);
});
console.log(filteredArray); // [ { age: 19 }, { age: 21 } ]
Enter fullscreen mode Exit fullscreen mode

Filtering Arrays by Search Criteria

A common use for filter is to take an array of values, and search through them based on a search term. This can be done with includes, or regex. For example:

let myArray = [ 'cat', 'catdog', 'dog', 'fish', 'fishcat' ]
let filteredArray = myArray.filter((element, index) => {
    return element.match(/cat/)
});
console.log(filteredArray); // ['cat', 'catdog', 'fishcat']
Enter fullscreen mode Exit fullscreen mode

Filter makes a Shallow Copy of Arrays

Although it may appear that filter makes a new copy of the original array, this is not the case. In fact, filter makes a shallow copy of the original array, which means that if we mutate objects within the array, the original will change too. To understand this, let's look at our age example again:

let myArray = [ { age: 4 }, { age: 12 }, { age: 19 }, { age: 21 } ];
let filteredArray = myArray.filter((element, index) => {
    return (element.age > 18);
});

console.log(filteredArray); // [ { age: 19 }, { age: 21 } ]

filteredArray[0].age = 50;
filteredArray[1] = { age: 40 };

console.log(filteredArray); // [ { age: 50 }, { age: 40 } ]
console.log(myArray); // [ { age: 4 }, { age: 12 }, { age: 50 }, { age: 21 } ]
Enter fullscreen mode Exit fullscreen mode

As you can see, modifying the filtered array using the filteredArray[0].age notation also modifies the original - but wait! filteredArray[1] = { age: 40 } changes only the filtered array. That's because although Javascript interprets the . notation as updating both arrays, it interprets the square bracket notation [] as setting a new value at the second position of the filtered array.

This is just another quirk of Javascript which can be confusing, but is very useful to know!

Conclusion

The filter method is widely used and an easy way to change create new subsets of arrays based on certain criteria. It should be noted that only a shallow copy is made of the original array, so modifying the array in certain ways will affect the original.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .