Understanding JavaScript Methods like Map(),Reduce(),Find(), and Filter()
Published: 2022-11-14 21:06:22

When learning how to code, you often come across particularly confusing methods. The idea of implementing/understanding callback functions is already daunting enough. However, now we have to implement those functions with difficult methods. The good news is that as a developer you have already taken the right steps to better understand how to implement these methods.

## What is a callback function?
Before we get into these methods we first have to understand what a call back function is first. The formal defintion of a callback function is. 

> A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

To summarize a callback function is a function that used as an argument inside another function. it will eventually be invoked (used) when the outer function is invoked.

Here is an example of a callback function being used
```javascript
function callBackFunction(){
   const sayHi = console.log("Hello! I am a callback function!")
   return sayHi
}
function mainFunction(callBackFunction){
    console.log("Hello! I am the main function.")
    callBackFunction()
}
mainFunction(callBackFunction)
```

  Here we created two functions mainFunction and callBackFunction. In our cute callback function we created a variable called sayHi which console logs the following message. the important thing to understand is that the callback function is not being invoked (used) just yet. The mainFunction on the first line console logs another message then on the second line of code it **invokes the callBackFunction inside itself**. In addition the mainFunction is not invoked yet either once we reach the last line of code in which we invoke both functions.

## Understanding .Map()
Now that we have a better understanding of callback functions we can start getting into these methods. The first method and the most used is the .Map() method. This method takes an array/object of elements and transforms each of them through a callback function of your choice. Then it takes those transformed elements and puts them into a new array. This is the formal definition.

>The .Map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

Let's break this further down. For example we have an array of elements.
```javaScript
const arrayOfElements = [1, 2, 3, 4]
```
For this example, we are trying to multiply all these elements by 2 However, I also want to leave original array alone in case I need to refer back to it later. This is when the .map() method comes in play.

First let's make a function that takes in an argument and mulitplies it by 2.

```javascript
function multiply(x){
return x * 2
}
```
Great! Now remember I do not want to change the original array so I am going to create a new array and equal it to the original array. Then we are going to attach our .map() method to the original array

```javascript
const newArray = arrayOfElements.map()
console.log(newArray)
```

This is good so far but we are still missing our callback function. The .map() method right now is taking every individual number in the orginal array but isnt doing anything with the numbers. Let's use the multiply function we created earlier as our callback function to tell the .map() method to multiply every number by two. With everything together it should look like this.

```javascript
const arrayOfElements = [1, 2, 3, 4]

function multiply(x){
return x * 2
}

const newArray = arrayOfElements.map(multiply)
console.log(newArray)
// expected Output: newArray [2, 4, 6, 8] 
```

## Understanding .Reduce()

The .reduce() method in simple terms attaches to an array of elements then goes through every individual element in that array. Then passes them through a callback function. During the first iteration the method takes that caculation performed in the callback function and saves it so during the next iteration it can be used. After passing every individual element into a callback function it then takes that new single element and saves it to a variable. This is the formal definition bellow.

>The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.

>The first time that the callback is run there is no "return value of the previous calculation". If supplied, an initial value may be used in its place. Otherwise the array element at index 0 is used as the initial value and iteration starts from the next element (index 1 instead of index 0).

Let's break this down. Let's say we have an array of numbers.

```javascript
const arrayOfNumbers = [1, 4, 6, 8, 12]
```

I want to know the total of these numbers. That's when our reduce method comes in! Let's create a new variable and equal it to this array of numbers and attach the reduce method to it.

```javascript
const arrayOfNumbers = [1, 4, 6, 8, 12]

const newArray = arrayOfNumbers.reduce()
```
Nice! so now we just need to give the reduce method arguments.
Right now the reduce method is taking every individual number in the array of numbers but isn't doing anything with them. With that in mind we are going to create a callback function so that the reduce method can do something with those numbers and for the second argument it is going to be our initial value(our starting point) but for now lets start it at zero.

```javascript
 const arrayOfNumbers = [1, 4, 6, 8, 12]

 const newArray = arrayOfNumbers.reduce(addTogether,0)
```
Now the only thing we need to do now is create the callback function. In this callback function it is going to need to take two arguments. The current number we are looping through in the array and the previous number from the previous caculation.

```javascript
function addTogether(currentNumber, previousNumber){
return currentNumber + previousNumber
}
```

During the first iteration the reduce method takes the first number which is 1 and passes it through the callback addTogether. In our callback function it takes that 1 and adds it to the intialized value we stated earlier which is 0 then returns that number 1 while also saving it to our currentNumber variable. Upon the second iteration reduce takes the second number which is 4 and passes it through our addTogether function. In that function it takes the saved number which is 1 and adds the current number which is 4 returning 5 while saving it. All together it should look like this

```javascript
 const arrayOfNumbers = [1, 4, 6, 8, 12]

 const newArray = arrayOfNumbers.reduce(addTogether,0)

 function addTogether(currentNumber, previousNumber){
  return currentNumber + previousNumber
}

console.log(newArray)
// Expected Output: 31
```
## Understanding .Filter() and .Find()

These last two methods are very similar in the fact that both of these methods take array/objects and take only the elements that meet the condition we setup in a callback function to then push those elements in a new array. Here is the formal definition for both.

>The filter() method creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function.

  
>The find() method returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.

The main difference between the two is when .find() gets an element that meets a condition it only returns that one element. While .filter() keeps looking for other matches throughout the other elements.

Let's start with the .filter() method let's say I have this array of elements.

```javascript
const originalArray = [apple, cherries, orange, banana]
```
In this example, we only need the fruits in which have a minimum word length of 5 characters. So let's start by creating our new variable that we want the array to be stored in and while we are doing that we can also attach the .filter() method to the original array.

```javascript
const originalArray = [apple, cherries, orange, banana]

const newArray = originalArray.filter()
```

Now we need to give our filter a callback function argument in which it can use to filter out the elements we do not want. In which case let's create a function called filterByLength to create that condition

```javascript
function filterByLength(individualFruit){
return individualFruit.length > 5
}
```
Awsome! With our callback function lets pass that into our .filter() and put it all together.

```javascript
const originalArray = [apple, cherries, orange, banana]

const newArray = originalArray.filter(filterByLength)

function filterByLength(individualFruit){
return individualFruit.length > 5
}
console.log(newArray)
//expected output: newArray [cherries, orange, banana]
```
Now that we have a good understanding of .filter() method the .find() method will be alot easier to understand. As mentioned earlier the only diffrence between these two methods is that the .find() method only returns the first element that meets the condition

Going back to the example let's say we replace .filter() with .find() we would only get back cherries and it would something like this

```javascript
const originalArray = [apple, cherries, orange, banana]

const newArray = originalArray.find(filterByLength)

function filterByLength(individualFruit){
return individualFruit.length > 5
}
console.log(newArray)
//expected output: newArray [cherries]
```

.find() stops at the first element that passes the condition in the callback.

## Conclusion
As developers we will always come across code we do not fully understand. That is why it is important to look up and refer back to the documentation when needed. These methods are going to be used in our every day lives so it's important to get a good understanding of them becasue they are here to help you not scare you.