What is a higher order function?
Higher order functions are functions that operate on other functions. This allows us to create functional abstractions and not just value abstractions.
In JavaScript, there are three commonly used higher order functions you should know about: map
, reduce
, and filter
. Let's look at each one with a real world example:
I want the names of employee's who's letter start with A
In order to do that, I will use the higher order function map:
map
const employees = [
{name: "Doug", gender: "M", occupation: "Help Desk"},
{name: "Alex", gender: "F", occupation: "CTO"},
{name: "Ada", gender: "F", occupation: "Developer"},
{name: "Sandra", gender: "F", occupation: "Developer"},
{name: "Beatrice", gender: "F", occupation: "Designer"},
]
let employeeNamesWithA = [];
employees.map((employee) => {
// Ternary opearator to check if an employee's name starts with A
return employee.name.includes("A") ? employeeNamesWithA.push(employee.name) : employeeNamesWithA;
})
//[ 'Alex', 'Ada' ]
But you can't just have an example and expect to understand, right? How is map a higher order function exactly? It takes a map of employees with properties and returns an array. Map makes a copy of the data so it WILL NOT modify the original one.
employees.map((employee) => {
Next we require another function for map, which is includes()
:
includes()
return employee.name.includes('A') ? employeeNamesWithA.push(employee.name) : employeeNamesWithA;
map
is used to programmatically iterate through a list
filter
Let's say I want to create a filter function for my dropdown that gives me results by occupation, but this time I want the object as well:
const employees = [
{name: "Doug", gender: "M", occupation: "Help Desk"},
{name: "Alex", gender: "F", occupation: "CTO"},
{name: "Ada", gender: "F", occupation: "Developer"},
{name: "Sandra", gender: "F", occupation: "Developer"},
{name: "Beatrice", gender: "F", occupation: "Designer"},
]
let employeesWhoAreDevelopers = employees.filter(employee => employee.occupation.includes("Developer"));
This method also WILL NOT affect the original data.
The
filter()
method creates a new array with all elements that pass the test implemented by the provided function.
reduce
Now, let's say your team needs to determine where to allocate their resources next. Because they don't want to be bothered by manually counting each other (much simpler, but so much potential for human error! /s), they would rather a program tell them instead (time is $$$, there are more important things to worry about, like this MVP that needed to be done YESTERDAY!). So, the goal is to group by occupation count. This will determine who the next person will need to be on the team:
const employees = [
{name: "Doug", gender: "M", occupation: "Help Desk"},
{name: "Alex", gender: "F", occupation: "CTO"},
{name: "Ada", gender: "F", occupation: "Developer"},
{name: "Sandra", gender: "F", occupation: "Developer"},
{name: "Beatrice", gender: "F", occupation: "Designer"},
]
const groupByEmployeeOccupation = employees.reduce((total, employee) => {
total[employee.occupation] = (total[employee.occupation] || 0) + 1;
return total;
}, {})
//{ 'Help Desk': 1, CTO: 1, Developer: 2, Designer: 1 }
Great! Now we have a decision to make. We ignore CTO, because there can only be one! And we find that after talking with Doug, he seems to be alright on his own right now. Beatrice on the other hand is swamped! We probably should've taken her point in retro for "Need to Improve: I need another designer", but now we at least have a program to tell us it's true!
So just what the heck is going on here? It looks more complex than map
and filter
right? How does reduce even work?
Well it takes two arguments (it can take four total, but not in this example) that function as an accumulator
and the currentValue
. An accumulator
is what to do with each iteration throughout the data. The accumulator will ultimately have a final resulting value of all the data. The currentValue
is what the iteration is currently at. So:
total[employee.occupation] = (total[employee.occupation]
total
is representing the accumulator
and taking the currentValue
, which is the employee's occupation key and setting it a value of how many times that occupation comes up + 1.
reduce
executes a reducer function (that you provide) on each element of the array, resulting in single output value
Summary:
- Higher order functions take a function as an argument
-
map
,reduce
, andfilter
are the most common examples of higher order functions in JS
Sources and Further Reading:
Top comments (0)