Visuals by: Julie Dorion-Bélanger. Thanks Julie!

Simplify your JavaScript – Use .map(), .reduce(), and .filter()

Etienne Talbot
poka-techblog
7 min readJan 29, 2018

--

If you’re starting in JavaScript, maybe you haven’t heard of .map(), .reduce(), and .filter(). For me, it took a while as I had to support Internet Explorer 8 until a couple years ago. But if you don’t need to be compatible with this very old browser, you have to become familiar with those methods.

Take note that this article most likely applies to whatever other programming language you might be using, as these are concepts that exist in many other languages.

.map()

Let me explain how it works with a simple example. Say you have received an array containing multiple objects – each one representing a person. The thing you really need in the end, though, is an array containing only the id of each person.

There are multiple ways to achieve this. You might want to do it by creating an empty array, then using .forEach(), .for(...of), or a simple .for() to meet your goal.

Let’s compare!

Using .forEach():

Notice how you have to create an empty array beforehand? Let’s see what it looks like when using .map():

We can even be more concise with arrow functions (requires ES6 support, Babel or TypeScript)

So how does .map() work? Basically is takes 2 arguments, a callback and an optional context (will be considered as this in the callback) which I did not use in the previous example. The callback runs for each value in the array and returns each new value in the resulting array.

Keep in mind that the resulting array will always be the same length as the original array.

.reduce()

Just like .map(), .reduce() also runs a callback for each element of an array. What’s different here is that reduce passes the result of this callback (the accumulator) from one array element to the other.

The accumulator can be pretty much anything (integer, string, object, etc.) and must be instantiated or passed when calling .reduce().

Time for an example! Say you have an array with these pilots and their respective years of experience:

We need to know the total years of experience of all of them. With .reduce(), it’s pretty straightforward:

Notice that I’ve set the starting value as 0. I could have also used an existing variable if necessary. After running the callback for each element of the array, reduce will return the final value of our accumulator (in our case: 82).

Let’s see how this can be shortened with ES6’s arrow functions:

Now let’s say I want to find which pilot is the most experienced one. For that, I can use reduce as well:

I named my accumulator oldest. My callback compares the accumulator to each pilot. If a pilot has more years of experience than oldest, then that pilot becomes the new oldest so that’s the one I return.

As you can see, using .reduce() is an easy way to generate a single value or object from an array.

.filter()

What if you have an array, but only want some of the elements in it? That’s where .filter() comes in!

Here’s our data:

Say we want two arrays now: one for rebel pilots, the other one for imperials. With .filter() it couldn’t be easier!

That’s it! And it’s even shorter with arrow functions:

Basically, if the callback function returns true, the current element will be in the resulting array. If it returns false, it won’t be.

Combining .map(), .reduce(), and .filter()

Since all three are called on arrays and since .map() and .filter() both return arrays, we can easily chain our calls.

Let’s check out another example. Here’s our data:

Our objective: get the total score of force users only. Let’s do it step by step!

First, we need to filter out the personnel who can’t use the force:

With that we have 3 elements left in our resulting array. We now need to create an array containing the total score of each Jedi.

And let’s use reduce to get the total:

And now here’s the fun part… we can chain all of this to get what we want in a single line:

And look how pretty it is with arrow functions:

Boom! 💥

Note: In my previous example, .map() and .filter() weren’t even necessary. We could easily achieve the same result with only .reduce(). I left them in there for the sake of this example. Can you guess how we could only keep .reduce() and get the same result with one line of code? See the solution on CodePen

Why not use .forEach()?

I used to use for loops everywhere instead of .map(), .reduce(), and .filter(). But a couple of years ago I started working a lot more with data that came from an API. That’s where I began to see the advantages of leaving .forEach behind.

Formatting

Say you need to display a list of people, with their name and job title.

The API gives you the above data, but you only need the title and the last name of each person… You need to format the data. However, your app also needs to have a single view for each person, so you must write a data formatting function that both works in a list view and in a single view.

That means you can’t have the .forEach loop inside of your formatting function, or else you would have to wrap your single element in an array before you pass it to the function just to make it work, like so:

So your loop has to wrap the call of the function, like this:

But .forEach() doesn’t return anything. It can’t. That means you have to push the results inside a predetermined array.

As a result, you have 2 functions: your formatElement() function and your function that pushes the results in your array.

Why have 2 functions when you can have just one?

Testing is easier

If you write unit tests for your code, you’ll find it simpler to test the functions you call with .map(), .reduce(), or .filter().

All you have to do is provide inbound data for the function and expect a result to come out. Basically “what comes out if this is passed?”. Less manipulation, less beforeEach()s and afterEach()s. It’s straightforward, simple testing.

Try it!

Try to replace some of your for loops with .map(), .reduce(), .filter() where it seems to fit. I guarantee your code will be way less clunky and much easier to read.

If you liked that article and want to learn more array methods, check out my article on how to use .some() and .find() in JavaScript.

Keep coding!

--

--

Etienne Talbot
Etienne Talbot

Written by Etienne Talbot

Software Engineering Manager at Poka, in Quebec City, Canada. I like Angular, Typescript, RxJS, a good scotch…