JS Basics: Higher Order Functions
Tags: basics, javascript, functional, composition
Published: 2020-08-17 03:28:40

---
title: JS Basics: Higher Order Functions
published: true
description: JS fundamentals
tags: basics, js, functional, composition
---

## 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()`](https://www.w3schools.com/jsref/jsref_includes.asp#:~:text=The%20includes()%20method%20determines,()%20method%20is%20case%20sensitive.): 
```
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`, and `filter` are the most common examples of higher order functions in JS 

Sources and Further Reading: 
- [Flashcards for Developers](https://www.flashcardsfordevelopers.com/decks/5b945d730d9bd6cbc6e66349/cards)
- [W3 School: Map](https://www.w3schools.com/jsref/jsref_map.asp#:~:text=Definition%20and%20Usage,for%20array%20elements%20without%20values.)
- [Mozilla: Reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
- [Mozilla: Filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)