JAVASCRIPT IRL: Examples of JavaScript's filter function in real life
Tags: javascript, codenewbie, webdev, arrays
Published: 2021-01-14 18:33:38

JavaScript array methods are super useful, and learning how to use them can really help improve the readability of your code. This is the third and final part of this series, and today I'll be discussing the `filter` function and how you can use it to make your code more concise. It's probably the easiest of the three to understand, since it's fairly straightforward, but it's always helpful to have examples on hand to understand exactly how it does and doesn't work.

Psst — don't have time to read through the entire article? Follow me on [Instagram](https://instagram.com/shaileshcodes) to get short, digestible posts on all things web development.

The `filter` function is called on an array and — like `map` — takes in one parameter: a callback. It performs this callback function on every element in the array, and includes the element in a **new** array if the callback returns true. Now, you might think that you can replicate this functionality without too much effort using `map`, but the key difference here is that `map` _always_ returns an array with the same length as the original. (Well, almost always, but that's a bit more complicated and not really in the spirit of `map` to begin with.) On the other hand, `filter` will create an array that's only as large as the number of elements that pass the callback.

That may seem like a lot, but it honestly works just like you'd expect to. Let's take a look at a simple example:

#### A trivial example

Here, we add filter the array to only include all elements greater than 2:
```javascript
      const arr = [1,2,3,4,5];
      const newarr = arr.filter(el => el > 2);

      console.log(newarr); // => [3,4,5]
```
The important thing to note here is that `newarr` is only of length 3; it doesn't return a `null` or `undefined` for the first two elements — it simply omits them entirely. We'll use this property to our advantage in the very next example.

#### Deleting caches (but properly this time)

If you've read my [article on the map function](https://shaile.sh/codes/posts/2021/01/06/javascript-map-in-real-life/), you'll recognize this example. However, it can still be improved: the `null` values that we returned could end up throwing an error later down the line. To avoid that, we're going to use `filter` to return an array that consists _only_ of the elements that match the condition.

This is what it looks like:
```javascript
      self.addEventListener('activate', e => {
        // Delete all caches that aren't named currentCache.
        e.waitUntil(
          caches.keys().then(cacheNames => {
            return Promise.all(cacheNames.filter(cacheName => {
              return cacheName !== currentCache;
            }).map(cacheName => {
              console.log('Deleting out of date cache:', cacheName);
              return caches.delete(cacheName);
            }));
          })
        );
      });
```
Again, very similar to the previous example. The key difference here is that _before_ we map each cache to its `delete` function, we're filtering out all the caches that don't match our condition. That way, the `currentCache` won't appear in the array being passed to the `map` and thus we avoid any `null` values.

Let's look another example:

#### Filtering posts in a blog

On my [blog page](https://shaile.sh/codes), I use a tagging system to allow users to filter content and view only the posts they're interested in. To do this, I actually created a JavaScript library called [dynamic-tags](https://svasandani.github.io/dynamic-tags/). While creating it, I needed to find a way to take all of the posts on the page and only display the ones that matched the given filter.

While this could have devolved into a nasty mess of `for` loops and `if` statements, I used the `filter` function to make things both readable and efficient. Here's how it ended up:
```javascript
      function filterPosts() {
        activePosts = posts;
        tagFilter.forEach(tag => {
          activePosts = activePosts.filter(post => tagDict[tag].includes(post));
        });
      }
```
Effectively three lines of code do much of the heavy lifting. In it, we go through each selected tag and call `filter` on `activePosts` to progressively remove any post that doesn't contain that tag. Even though `filter` might seem like a very minor abstraction over a plain `for` loop, we can see in this example just how concise and readable it makes your code.

Let's take a look at one final example:

#### Making things searchable

As an extension to the library I created above, I also wanted to create a system where users could search for topics and filter posts based on that. This is still a work in progress, but it already includes several useful examples of the `filter` function in action.

Let's take a look at my favorite one:
```javascript
      populateSearchBox(el) {
        let searches = this.allTags.filter(tag => tag.toLowerCase().includes(el.childNodes[0].data.toLowerCase()));

        let searchBox = this.filter.querySelector(this.classListToSelector(this.searchBoxClass));
        if (searchBox) {
          searchBox.innerHTML = "";

          searches.forEach(search => {
            if (!this.tagFilter.includes(search)) this.addTagTo(search, searchBox, false);
          });
        }
      }
```
In this snippet, instead of filtering out posts, we're actually filtering out suggestions in the search box. Here, the `filter` function is used to ensure we're only appending suggestions that haven't already been selected. That is, we don't want a user to be filtering by topics that they've already filtered out.

The actual `filter` function is quite interesting — it looks for all the tags that contain the phrase inside the search bar. For example, given the tags `['May', 'June', 'July']`, typing a 'y' into the search bar should return `['May', 'July']`. On the other hand, typing 'J' should return `['June', 'July']`.

#### Wrapping it up

And that's a wrap! I hope these examples gave you an idea of how the `filter` function is used in production, and how it can help make code more readable and versatile. Let me know in the comments if you've used the `filter` function in a cool way, and make sure to read the other two posts in the series if you haven't already!

As always, don't forget to follow me for more content like this. I'm currently writing on [dev.to](https://shaile.sh/devto) and [Medium](https://shaile.sh/medium), and your support on either platform would be very much appreciated. I also have a [membership](https://www.buymeacoffee.com/shailesh/posts) set up, where you can get early previews of articles and exclusive access to a whole bunch of resources. Also, if you've particularly enjoyed this post, consider supporting me by [buying me a coffee](https://shaile.sh/coffee). Until next time!