What Are JavaScript Higher Order Functions? .map, .filter, and .reduce explained!
Introduction
Higher order functions in JavaScript such as map
reduce
and filter
can completely transform the way you write your code. They are some of the most useful functions when it comes to manipulating data from regular arrays to fit any condition or format you desire.
In this guide, we'll quickly go over how you can utilize these functions, how they work step-by-step, and some common use cases for you to utilize them in your projects.
Why Higher Order Functions?
One of the core concepts of functional programming is the treatment of functions as first-class entities.
This means we can pass functions as arguments to other functions, store functions in variables, and return a function from another function.
Functional programming stems from the declarative paradigm, in which you describe "what" the program should do, rather than the exact steps on how to do it.
Something that has drastically improved the way I write my code is writing in a more declarative manner.
An example of what this looks like is, rather than the traditional for loops that I'm sure you are all familiar with, that look like this:
// Imperative style programming - describing "how" to do it.
const arr = [1,2,3,4,5];
let arr2 = [];
for (let i = 0; i < arr.length; i++) {
arr2[i] = arr[i]+1
}
console.log(arr2) // [2,3,4,5,6]
We can convert our code to be much cleaner, with a more declarative style of coding:
// Declarative style programming - describing "what" to do.
const arr2 = [1,2,3,4,5].map((i) => i + 1)
console.log(arr2) // [2,3,4,5,6]
While this example is very simple, the benefits of writing in this way are well worth it:
- Cleaner code (Easy to quickly understand and easier to write)
- Immutability (No opportunity to directly mutate initial array)
- Less chance of bugs in our manually written
for loop
.
All of the functions that we are going to discuss in this blog post apply a function
to each element
of an array
; and meet the criteria of being a higher-order function, due to the passing of a function as an argument.
Let's get into the details of the functions map
, filter
, and reduce
now.
Map Function
The JavaScript map
function allows you to apply a function to all elements of an array.
map
will output a new array, containing the result of running each item in the array through a function that you provide.
In our previous example above, we applied a function that added 1
to each item in an array.
Image Example
In the above example, we are applying an imaginary cook
function, to each item in the array.
Here is how this works:
- In sequential order, grab the next item in the array
- Apply the function to the item (in this case
cook
) - Place the item returned from the applied function at the end of a newly created array.
- Repeat this process until there are no more items in the initial array.
My favourite use case of the map
function is to transform an array of items into React components.
For example, let's say I have an array of peoples names:
const names = ['Jarrod Watts', 'Sandeep Panda', 'Syed Fazle Rahman']
I can convert this list of names into React Components (in this example, just plain HTML) while inside JSX, by using map
and passing a function to transform each name in the array, into a new <li>
element.
<ul>
{ names.map((name) => (
<li>${name}</li>
)) }
</ul>
The output of this code would be:
<ul>
<li>Jarrod Watts</li>
<li>Sandeep Panda</li>
<li>Syed Fazle Rahman</li>
</ul>
Filter Function
The filter
function returns a new array of items, which pass the criteria of a predicate function.
In simpler terms, we pass in an array of items, as well as a "test", and run each item of the array through that test.
If the item passes the test, it is included in the output array. If the item fails the test, it is not included in the output array.
Image Example
Here's how this works, for each item in the initial array:
- Run the item through the test function
- If the item passes the test, include it in the output array
- Repeat for each item in the array.
An example use case for the filter
function is to filter out any undefined
data you might have in an array.
For example,
const data = ["hashnode", "is", undefined]
// We could filter out the undefined data by saying
const filteredData = data.filter((x) => x != undefined)
console.log(filteredData ) // ["hashnode", "is"]
Reduce Function
reduce
is usually considered the scariest of the three!
Reduce allows you to convert an array into a single output value. The output can be almost anything, a number
, a string
, another array
, or even an object
.
Reduce is a bit different to map
and filter
, because it keeps an accumulator
value in addition to the current item being iterated over.
This is different to map
and filter
which do not have an accumulator value, and simply use the current item.
After iterating over all the items in the array, the accumulator
value is the value that gets returned.
Image Example
Let's try and break down how a real example of reduce
works.
The most simple example of reduce
is to add up all the numbers in an array. Let's review how that is possible:
const arr = [1,2,3,4]
const sum = arr.reduce((accumulator, currentValue) => accumulator + currentValue);
console.log(sum) // 10
Notice how the function we are passing in now takes 2
parameters.
The first parameter, accumulator
is the represents the result of all outputs that have occurred thus far.
The currentValue
is what we have seen in before in map
and filter
; where we can access the current item being iterated over.
What does it mean when we're talking about the accumulator
representing the "result of all outputs that have occurred so far"? Let's break it down step by step:
The flow of the example reduce
function we are demonstrating below is what happens at every step of the way. If it's not clear, we are attempting to produce the sum of all items in an array.
// Since we don't pass in a default value (which you CAN do),
// accumulator is the first item in the array: 1.
arr.reduce((accumulator,
// currentValue is then the next item in the array: 2
currentValue) =>
// Define a function to do something with accumulator and currentValue
accumulator + currentValue)
// First iteration:
// Accumulator = 1
// CurrentValue = 2
// 1 + 2 = 3
// Accumulator is now 3
// Second iteration:
// Accumulator = 3
// CurrentValue = 3
// 3 + 3 = 6
// Accumulator is now 6
// Third iteration:
// Accumulator = 6
// CurrentValue = 4
// 6 + 4 = 10
// Accumulator is now 10
// No more items in array
// Return final value of accumulator: 10
Conclusion
In this quick blog post, we've explored three of the most powerful functions in JavaScript:
map
filter
reduce
In addition, we've explored the benefits of using these higher-order functions and why they are so special in the JavaScript world!
Outro
If you enjoyed this kind of content, consider giving me a follow on Hashnode!
I also am active on a number of other social platforms, posting content just like this! I'd love for you to check them out:
- YouTube ๐ youtube.com/c/jarrodwatts
- Twitter ๐ twitter.com/JarrodWattsDev
- GitHub ๐ github.com/jarrodwatts
- Tik Tok ๐ tiktok.com/@jarrodwattsdev
- Website ๐ jarrodwatts.com
If you're feeling really generous, you can support me with Hashnode's Sponsor feature - which all goes directly to me, and then invested back into more content like this!
Sponsor Me ๐ blog.jarrodwatts.com/sponsor โค๏ธ
Thanks for reading!