JavaScript is a language with many capabilities. There is no single concrete way to solve a problem and you have the freedom to approach it however you want. There are many ways to make async calls and handle responses, many ways to handle events and many ways to handle array operations. In this article we’ll focus exactly on arrays and how the built in methods on its prototype can make our life much easier.
One of the most common things we do is iterating over arrays. Maybe we are looking for a certain person in a list of people or we are calculating the total of all orders. Something I often have to do is pulling only certain properties from a list of objects. Most developers would reach for the loop when they need a tool for solving such a task.
Here we have the mundane and totally realistic operation of multiplying all the numbers in an array by two and storing them in a new array. Notice how unpleasant this looks. If we need to apply conditional checks to the numbers it gets even worse:
Thankfully, we can use the built in map, filter and reduce higher order functions to simplify this code and write those operations on a single line, thus improving our overall code quality. Before we dive in — higher order functions are a term that you will often see in JavaScript. These a functions that take as input or return another function. You have already used those in event callbacks or requests, but it’s good to know the term. Map, filter and reduce are all HOC because they take a function as a parameter as you will see.
Map is a function on the Array object’s prototype which takes a single input — a callback function. What map does is that it will go through every element on the array it is called on and it will execute that function. The callback is passed the element we are currently mapping over so we can make any transformations or calculations that we need. After we go through each element, map will return a new array containing the result of the mapping.
Map can be a bit misleading at first, but once you get used to it you will always prefer it to loops. This is the same example that we had earlier in the article but written with a single line of code. We’re taking advantage of ES6 arrow functions to simplify our code as much as possible. We omit parentheses around the input x, because it’s a single input and we can also omit the return statement. In the older syntax this function would look like this:
Still, quite clean and better than the loop, but my personal preference is to go with the arrow functions whenever I can.
Filter is another function on the Array object’s prototype and takes a callback function as a single input. Filter will go through all of the values of our array, it will execute the callback function and return a new array containing only the values that we have decided to pass.
How do we define a rule for the filtering? The function that we pass to filter will have access to the variable it is currently iterating over and must return true or false. If the returned value is true it will add it to the result array, if it’s false it will skip it.
Do you see how simpler this is than the example with the loop that we had earlier? The expression inside the callback will return true or false which is enough for our function, we don’t even need an if statement.
Reduce is the most powerful function of all three and the hardest one to understand. There are many things that you can do with reduce, you can even use it as a replacement for map and filter. It is again called on an array and it will reduce it to a single variable. The easiest example to understand reduce is by calculating the total of an array of numbers.
Another difference between reduce and the other two is that here you have to work with two variables inside the callback. One of them is the current value that we’re iterating through, the other is the persisted one. In this particular example the accumulator variable will hold the total. I used the longer example for clarity but it can also be done with an arrow function on a single line:
The main concept about reduce is that it will return a single value after it has finished — the one it has accumulated throughout the iterations. Unlike map and filter, reduce takes a second parameter besides the callback function. It also accepts an initial accumulator value which means that we can use it for other things than just mathematical operations. We can even use an array or object as initial value. An interesting example to get your creativity going is counting the number of times a certain element appears in a list.
These functions are really powerful on their own, but by using them together we can take full advantage of them. As mentioned each one of those functions returns a new array instead of modifying the existing one. Therefore we can use them one after the other and the next one will always return the result from the previous operation. Let’s have a look at a more advanced example in which we are chaining the methods and are using named functions:
Understanding map, filter and reduce will drastically improve the quality of code you’re writing. The examples are over simplified for the sake of the article, of course you can use collections of any type. Remember that using those functions will not mutate the array you’re calling them on, they will return an entirely new value and if you don’t store it or do something with it it will be lost. Also keep in mind the function input order in reduce. If you mix it up you will get unexpected and interesting results.
Thank you for the read!