Higher Order Functions
Tags: javascript, beginners, programming, functions
Published: 2023-08-17 17:37:03


## What are Higher Order Functions?
Simply put, higher order functions are functions that accept single or multiple functions as arguments and/or return functions as their output. The functions that are used as arguments are called **callback functions**.

We can do this because functions are first class objects. This basically means functions can act just like other datatypes. For example, you can assign a function to a variable which is called a **function expression**. Additionally, functions can be stored in objects and arrays. 

```
//function expression
let funcVariable = (a, b) => a + b

//function as an object's value
let funcInObj = {
fullName: (first, last) => `${first} ${last}`
}
//functions as values in an array
let funcInArr = [(first, last) => `${first} ${last}`, (age) => `I am ${age} years old`]
```
Unlike other datatypes, functions not only store data, they often perform an action in your code. By accessing the function assigned to the variable or within the object or array, you can call the function and create an action in your code.

```
//calling a function assigned to a variable
funcVariable(6, 7) //will return 13

//calling a function in an object
funcInObj.fullName('Ilana', 'Wexler') //will return Temperance Brennan

//calling a function in an array
funcInArr[0]('Abbi', 'Abrams') //will return Seeley Booth
funcInArr[1](26) //will return I am 26 years old
```
Now that we understand what higher order functions are and why we can use them in this capacity, we will dive deeper into _how_ to use higher order functions in our code by taking a look at common array methods that are actually higher order functions. 


## Common Higher Order Functions and How to Use Them
.filter(), .map(), and .reduce() are native methods in JavaScript that allow us to easily manipulate datasets using higher order functions. Behind each of these methods are for loops that access each element in the input array so you can call various functions on each value. These methods decrease the number of lines of code we must use and allow for more efficient coding. Below we will dig into how to use each of these methods.  

**.filter()**
The .filter() method is designed to take in an array and a function. The callback function tests each element of the array and will only return the values that pass the function's test as a new array.

Let's say you have a data set of customers and you want an array of only the customers over 40. The .filter() method would be a great way to get this information.
```
let customers = [
{name: 'Ilana Wexler',
city: 'New York City',
age: 21
},
{name: 'Temperance Brennan',
city: 'Washington DC',
age: 45
},
{name: 'Abbi Abrhams',
city: 'New York City',
age: 26
},
]

let over40 = customers.filter((current) => current.age > 40)
console.log(over40) //will log [ { name: 'Temperance Brennan', city: 'Washington DC', age: 45 } ]
```
As you can see if the code above, we are using the filter method on our array of customers with a callback function that is  testing each element to see which customer has an age value over 40. Because of .filter()'s behind the scenes code, this pushes all of the elements that pass this test into a new array.

**.map()**
The .map() method is designed to take in an array and a function and return an array of new values based on the actions of the function. In other words, the callback function is called on each item in the array. These updated values are then pushed into a new array which is returned.

Let's say we wanted to output a new array of customer objects with an additional property. The .map() method can help us do this.

```
let updatedCustomers = customers.map(current => {
  return {
    name: current.name,
    city: current.city,
    age: current.age,
    lovesPizza: true
  }
})
```
Using the .map() method we are able to create a new array by calling this callback function that adds a new key/value pair to each of the elements of the input array. 

**.reduce()**
The .reduce() method is designed to take in an array, a function, and a seed and return an accumulated value based on the action the function performs on the array. The seed value is optional but should be used if you want to return a value that is not an array. 

The callback function accepts two values, typically referred to as _accumulator_ and _current_ but can be labeled with any name. The value of the _current_ parameter is an individual value from the input array. 

Let's say you wanted to know how many customers in your data set live in New York City, the .reduce() method would be a great way to find this out.

```
let findNYCResidents = customers.reduce((accumulator, current) => {
if(current.city === 'New York City'){
accumulator += 1
}
return accumulator
}, 0)
console.log(findNYCResidents) //will return 2
```
.reduce() is a very powerful method that has many uses because of the flexibility the seed value allows. Here we access each value in the array and pass it through our callback function that adds 1 to our accumulator every time a customer passes the callback function's test.

**Understanding higher order functions is very important in being able to create flexible, efficient code, so I hope you were able to take away a better understanding after reading through!**