Understanding the .map(), .filter() and .reduce() array methods in Javascript.
Tags: javascript, beginners, programming
Published: 2022-08-02 13:53:00

Arrays are one of the most used data structures in Javascript, from storing basic data in our code to getting results from API calls. As Javascript developers were always working with arrays and carrying out some form of operation on them. 

The .map(), .reduce() and .filter() are some of the lesser-known array methods released in ES6, that uses a more functional and cleaner approach to carry out array operations.

In this article, we’ll be taking a detailed look at how these array methods work and how we can use them to carry out some basic operations.


## Overview

First a brief look at what these array methods do.

The **.map()** method returns a new array where each element have gone through an operation of some kind.

The **.filter()** method returns a new array containing only array elements that passed a specific condition.

The **.reduce()** method reduces all the elements in the original to a single value. 

These array methods are Higher Order Functions, meaning they take callback functions as parameters.


## The .map() method
The **.map()** method returns a new array that contains the result of applying an operation on each of the original array elements.
  
The *.map* method accepts a callback function as a parameter and an important parameter for the callback function is the *element* parameter, the *element* parameter is processed by the callback function and returned an element to the new array.

Syntax for the .map() method
```javascript
Array.map(function (element) {
	//operation on element
})

//using arrow function
Array.map(element => {
    //operation on element
})
```


### Using the .map() method
```javascript
let numbers = [24, 11, 8, 13]

const double = numbers.map(number=> score * 2)
console.log(double) 
// outputs [ 48, 22, 16, 26 ]
```

When we run the code above. The *.map()* function loops through the numbers array, assigns the current element in iteration as ***number***, carries out the operation **number \* 2**, and then finally inserts this new value to the new array. 

Note that the *.map()* method will always return an array of the same length as the original array. 


For the rest of this tutorial, we'll be working with an array of objects, that contains the name, occupation and score of a group of employees.

```javascript
const employees = [
  {
    name: "Peter",
    score: 25,
    occupation: "Engineer"
  },
  {
    name: "Judy",
    score: 30,
    occupation: "Banker"
  },
  {
    name: "Jarvis",
    score: 40,
    occupation: "Doctor"
  },
  {
    name: "Paul",
    score: 65,
    occupation: "Engineer"
  }
]
```
The .map() method can also be used to extract specific data from an array
With the *.map()* method, we can get the names of all the employees to a new array.

```javascript
const names = employees.map(person => person.name)
console.log(names) 
//returns ["Peter","Judy","Jarvis","Paul"]

```

### More callback parameters
The *.map()* callback function can take more parameters that you might find useful when carrying out array operations.  

>```javascript
Array.map((element, index, array) {operation})
```

The **element** parameter is used to access the current element in iteration.  

The **index** returns the index of the current element in iteration  

the **array** returns the complete original array. 

I personally haven't seen any use case for the **array** parameter. If you have seen please comment below.




## The .filter() Method

The .filter() returns a new array containing only elements that passed the condition passed in the callback function.

Syntax for the .filter() method
```javascript
Array.filter(element => {
	//condition
})
```

```javascript
let numbers = [24, 11, 8, 13]

const filter =  numbers.filter(number => number > 10)
console.log(filter)  
// output [24,11,13]
```
When we run the code above the *.filter()* method loops through the numbers array, and checks if the current *number* is greater than 10, if true the number is added to the new array.

### Using the .filter() method

We can use the .filter() method to get the array of employees who are engineers from our data above.

```javascript
const allEngineers = people.filter(person => person.occupation === "Engineer")
console.log(allEngineers)
//Outputs 

[
  {
    name: "Peter",
    score: 25,
    occupation: "Engineer"
  },
{
    name: "Paul",
    score: 65,
    occupation: "Engineer"
  }
]
```


### Optional callback parameters
 
The **.filter()** callback function just like the .map() can also take more than just the **element** parameter as an argument and they also serve the same purpose.

```javascript
Array.filter((element, index, array) {condition})  
```

  
## The .reduce() method. 

The  **.reduce()** method is used to combine all the elements in an array to get a value. It evaluates all of the elements in the array to return a single value.

The *.reduce()* method is a little more complicated than the other two mentioned above because its callback function requires a specific parameter known as the “accumulator” which holds the total value during the operation and returns it after the operation is completed. This "accumulator" parameter is used in the reducer function.

Syntax for *.reduce()* method

```javascript
Array.reduce((accumulator, element) {
	//reducer
}, initial value)
```

Using the .reduce method to get the sum of numbers.

```javascript
let numbers= [24, 11, 8, 13]

const sum =  numbers.reduce((sum, number) => {
  return sum + number
}, 0)

console.log(sum)  
// outputs 56
```

When the code above runs the *.reduce()* method first set the value of **sum** to *0* which was provided as the initial value and then loops through the array, on every iteration, it adds ***number*** to the value of **sum**, and after the last element returns **sum** which in our case is 56.


While the initial value might be optional it's always advisable to specify it, to avoid getting a ***TypeError*** in the case of an empty array. We get the error message below.

> Uncaught TypeError: Reduce of empty array with no initial value



## Chaining Methods
One of the pros of using these array methods is the ability to chain them. Since unlike the ***.forEach()*** method these array methods return a new array, we can chain them to get a combo method.

Chaining is combining array methods to perform operations on them and get a final return value.


Using chaining we can get the names of employees who scored above 35.
```javascript
const passed= people.filter(person => person.score > 35)
  .map(person => person.name)

console.log(passed)
 // outputs ["Judy","Jarvis","Paul"]
```
In the code above the .filter() operation is carried out first on the array which returns an array of employees whose score is above 35 then the .map() method returns their name as the final value of the operation.

We can also get the sum of the scores of engineers only.
```javascript
const engineersScore= people.filter(person => person.occupation === "Engineer") //return an array of engineers only
    .map(person => person.score) //returns the array of engineers score
    .reduce((sum, element) => sum + element) //sums up the score.

console.log(engineersScore)
//outputs 90
```

## Conclusion
The best way to master new concepts is by using them. Try using these methods in place of the *.forEach()*  when possible. 

Feel free to comment below if you have any feedback and please share with other Javascript developers.

Let's Connect on [Twitter](https://twitter.com/SamJarvis244)

### Resource I used
[MDN](https://developer.mozilla.org/en-US/)