Get Started With The ES6 Array Methods .filter(), .map() and .reduce()
Tags: javascript, webdev, beginners
Published: 2019-06-30 20:14:09

ES6 comes with many new features. One of which are a few very handy `Array` functions. The most popular for doing daily tasks are `.filter()`, `.map`, `.reduce()`. In this post, I'll cover each one with examples of first the "old" way, then with these new functions.

*This post assumes you know about arrow functions. If you don't know what they are, don't worry. Read the first chapter of my [blog post on array functions](https://developer.blog/es6-arrow-functions) and you should be good to go for understanding what's going on here.*

## What they all have in common

All three functions were introduced in ES6 (ECMAScript 2015) and are functions that are **applied to an `Array`**.

Also, all of them as so-called *higher-order functions*. That means that they are a function which return functions as results or **take other functions as parameters**. In this case, it's the latter. That is very important to understand for this lesson.

On the inside, these functions **run a forEach loop** and then apply the passed function in one way or another to the data it's iterating.

## .filter()

The easiest for me to understand was, `.filter()`. It does exactly what it says - It takes the existing array  and returns a part of that array back, possibly skipping some value. Or in other words: Take out the items we don't want.

Having the following array of people with an age.
```javascript
const people = [
    { name: 'John', age: 32},
    { name: 'Isabelle', age: 18},
    { name: 'Steve', age: 17},
    { name: 'Winston', age: 10},
    { name: 'Agnes', age: 82}
]
```

Now we want to get only the people back that are of full age, or in other terms *filter out* the minors. Let's assume for this exercise we live in a country where 18 or higher means you're of full age. 

If we were to write this statement without the `.filter()` function, it'd go something like this:

```javascript
let adults = []
people.forEach(person => {
    if(person.age >= 18) {
        adults.push(person)
    }
})
```

With the ES6 `.filter()` function if would look like this:
```javascript
const adults = people.filter(person => person.age >= 18)

// Will outout the objects for John, Isabelle and Agnes...
console.log(adults)
```

Let's break this down...
- As a parameter we pass a function
- That function (for this example) takes one parameter (here: `person`)
- That parameter refers to the current element being iterated in filter()'s forEach.
- The **function we pass returns a boolean** as a value. That boolean value indicates whether the current element is filtered out or not (`true` = stays in the array, `false` = is being skipped)
- As condition for this boolean we have if the age of the person is higher or equal to 18.

**Heads up!** To make this blog post simpler, I won't explain all the parameters that *can* be passed. For further details on optional parameters, check out the [MDN docu on filter()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).

## .map()

`.map()` also returns an array as a result. But this time we won't filter anything, but fill the new array with data that's calculated from the original array.

Let's assume this array we have on degrees in degrees Celsius:
```javascript
const celsiusArray = [ 21.5, 33.5, -7.1, 12.6 ]
```

If we were to convert this to the same array, but with degrees Fahrenheit, we *could* do that traditionally like this:

```javascript
let fahrenheitArray = []
celsiusArray.forEach(celsius => {
    fahrenheitArray.push((celsius * 9/5) + 32)
})
```

If we want to write the same thing using `.map()`, it would look like this:

```javascript
const fahrenheitArray = celsiusArray.map(celsius => (celsius * 9/5) + 32)
```

> Note, that unlike in the `.filter()` example, the array size of the original array and the output array is always the same when we use the `.map()` function.

Let's analyze what happened here...
- As a parameter we pass a function
- That function (for this example) takes one parameter (here: `celsius`)
- That parameter refers to the current element being iterated in filter()'s forEach.
- The **function we pass returns a value of any type we want**
- That value is the one that will be inserted in the new array.

**Heads up!** To make this blog post simpler, I won't explain all the parameters that *can* be passed. For further details on optional parameters, check out the [MDN docu on map()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).

## .reduce()

This function is the only one of the three that don't return an array. Instead, it returns a single value.

This means, the functions uses the information from the array and calculates something out of it. What it calculates depends solely on the function we give it.

Let's assume this array of products consumed in a restaurant:

```javascript
const foodOrder = [
    { name: 'Pizza Diavola', price: 15.9 },
    { name: 'Sparkling Water', price: 2.9 },
    { name: 'Tiramisu', price: 6.5 }
]
```

If we want to calculate the sum of the food items display the total on the customer's ticket, including 17% VAT, we would do something like the following if we didn't knew about the .reduce() function:

```javascript
let sum = 0
foodOrder.forEach(food => {
    sum += food.price
})
```

With `.reduce()` it would look like this:

```javascript
const total = foodOrder.reduce(( accumulator, food ) => accumulator + food.price, 0);
```

> Note, that unless like in the other two functions, `.reduce()` does not return an array, but a single value.

So what happens in the example above?
- `.reduce()` iterates through our array and calls our function with every food item
- The first item `accumulator` is the current "total" value the loop has calculated up to that point
- `food` is the current items that's been iterating through
- The **return value** of our passed function is **whatever calulcation we want to do**, working with the `accumulator` and `currentValue` (in this case add the two)
- There would be just one hiccup: There must be an initial value in most times for this kind of calculations. Luckily ES6 provides us with an optional parameter (2nd in the `.reduce()` function)

**Heads up!** To make this blog post simpler, I won't explain all the parameters that *can* be passed. For further details on optional parameters, check out the [MDN docu on reduce()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).