JavaScript: Higher-order functions Part-2
Tags: javascript, programming, beginners, webdev
Published: 2021-04-05 03:09:32

### JavaScript: Higher-order Functions

1. Array.prototype.map
2. Array.prototype.filter
3. Array.prototype.reduce
4. Array.prototype.forEach
5. Array.prototype.every
6. Array.prototype.some

### 2. Array.prototype.filter()

Filter method creates a new array which contain all the elements which satisfies the condition contained in the callback function.

```javascript
// Syntax
let newArr = arr.filter(callback(currentVal, index, array) {
    // code to execute
},thisArg);
```
Callback function contain condition to test each element of the array, the return value is the element itself if the element satisfices the test condition, else the element is not included in the output. "currentVal" is the current element of the array which is being passed into the callback function. "index" is the index of the current element in the array, index is optional. "array" is also optional, the "array" is the array in which filter is being called. "thisArg" sets the value to callback's "this", it is optional, if not provided the value will be "undefined". Lets look at an example to understand the working. 

```javascript
let arr1 = [1, 27, 49, 6, 8, 11, 5, 20, 19, 15, 2];
let arr_filter = arr1.filter(elem => elem%2 == 0 );
console.log( arr_filter); //[6, 8, 20, 2]
console.log(arr1); //[1, 27, 49, 6, 8, 11, 5, 20, 19, 15, 2]
```
In the above code the filter method is called on the "arr1" array, here the filter condition is to find the even numbers in the array. The equivalent of the above code without filter function is given below.

```javascript
let arr2 = [1, 27, 49, 6, 8, 11, 5, 20, 19, 15, 2];
let arr_filter2 = [];
for (i = 0; i < arr2.length; i++) {
     if (arr2[i] % 2 ==0){
          arr_filter2.push(arr2[i]);
     }           
}
console.log(arr_filter2)              // [6, 8, 20, 2]
```
One more example of filter method
```javascript
var names = ["kiran", "vishnu", "manu", "varun", "adi"];
let names_filter = names.filter((elem)=> {
    elem.charAt(0) == "k" || elem.charAt(0) == "v");
}
console.log(names_filter) //["kiran", "vishnu", "varun"]
```
### 3. Array.prototype.reduce()
Reduce() method executes a reducer function on each element of the array and return a single output value. 

```javascript
// syntax
arr.reduce(reducer(accumulator, currentValue, index, array){
    //code to execute
}, initialValue)
```

"InitialValue" is an optional value, used to set inital value in the reduce method. When reducer function is called for the first time, if "initialValue" is provided, then accumulator will be equal to "initialValue", and "currentValue" will be equal to the first element in the array. If no "initialValue" is provided, then accumulator will be equal to the first element in the array, and "currentValue" will be equal to the second element in the array. "index" is the index of the current element in the array, index is optional. "array" is the array in which filter is operating; an optional value.

If the initial value is provided and the array is empty the initial value is returned without calling the reducer since there is nothing to reduce. If the initial value is not provided and the array contains a single element that array element will be returned without calling the reducer function . 

Let's look at some examples.
```javascript
var num= [10,2,5,6,7]
let sum = num.reduce((acc, cv) => acc + cv);
console.log(sum); //30
```
In the above example reduce method is called on to the "num" array, the reduce function reduce the array by adding elements one to the other and produce total sum as the result.

```javascript
// with inital value set
let sum2 = num.reduce(function (ac, cv) {
     return ac + cv
}, 0);
console.log(sum2);  // 30
```
The equivalent of the above code without reduce method is given below.
```javascript
// No higher-order functions
var num= [10,2,5,6,7]
let sum1 = 0
for(i = 0; i<num.length; i++){
    sum1+=num[i]
}
console.log(sum1);  //30
```
Some more examples

```javascript
// Code to get the sum of nested array
let arr3 = [[10, 5], [50, 0], [100, 35]]
let arrSum = arr3.reduce(
    function(ac, cv) {
        return ac.concat(cv)
    }).reduce((ac,cv) => ac + cv)
console.log(arrSum); //200
```

```javascript
let arr1 = [10,20,30,40,50];
let sum1 = arr1.reduce((ac, cv, index, array) => { 
    console.log(`Accumulator:${ac}  Current value:${cv}  
        Index:${index}  Array${array}`);
    return ac + cv;
},0)

// Accumulator:0  Current value:10  Index:0  Array10,20,30,40,50
// Accumulator:10  Current value:20  Index:1  Array10,20,30,40,50
// Accumulator:30  Current value:30  Index:2  Array10,20,30,40,50
// Accumulator:60  Current value:40  Index:3  Array10,20,30,40,50
// Accumulator:100  Current value:50  Index:4  Array10,20,30,40,50
```
### 4. Array.prototype.forEach()

forEach() method executes the callback once for each element

```javascript
arr.forEach(callback(currentVal, index, array) {
  // code to execute
},thisArg);
```
"currentVal" is the current element of the array which is being passed into the callback function. "index" is the index of the current element in the array which is an optional value. "array" is the array in which filter is executing, it's optional. "thisArg" is the value passed to "this" of the callback during execution if no value is provided the value will be "undefined", it is also an optional value. 

forEach() method always returns the value "undefined" so it cannot be assigned to value to get the result of callback and is not chainable. forEach() method expects a synchronous function and due to this it will not wait for promises. ForEach will not invoke callback for deleted or uninitialized elements.

```javascript
let arr1 = [10, 20, 30, 40, 50];
arr1.forEach((elem) => console.log(elem*elem));

//Output
//100
//400
//900
//1600
//2500
```
Some more examples 
```javascript
// forEach always return "undefined"
let something = arr1.forEach((elem) =>  elem* elem);
console.log(something);   //undefined

// Code to return the output as an array
let resultArr = []
let result = arr1.forEach((elem)=>{resultArr.push (elem* elem)});
console.log(resultArr);   //[100, 400, 900, 1600, 2500]
```
```javascript
let arr = [10, 20, 30, 40, 50];
arr.forEach((elem, index, array) => { 
    console.log(`Element:${elem}  Position:${index}  
        Array:${array}  Result:${elem*elem}`)
});
// Element:10  Position:0  Array:10,20,30,40,50  Result:100
// Element:20  Position:1  Array:10,20,30,40,50  Result:400
// Element:30  Position:2  Array:10,20,30,40,50  Result:900
// Element:40  Position:3  Array:10,20,30,40,50  Result:1600
// Element:50  Position:4  Array:10,20,30,40,50  Result:2500
```

[JavaScript: Higher-order functions Part-1](https://dev.to/kiranrajvjd/javascript-higher-order-functions-3gi1)
[JavaScript: Higher-order Functions Part-3](https://dev.to/kiranrajvjd/javascript-higher-order-functions-part-3-4p9d)