JavaScript: Higher-order Functions Part-1
Tags: javascript, webdev, beginners, programming
Published: 2021-04-04 13:47:40

Any function which take another function as argument or return a function is called a higher-order function.

In JavaScript functions
1. Can be assigned to a variable.
2. Can be passed as argument to another function.
3. Can be returned by another function.
4. Can be set as object properties.
5. Can be passed in an array element.

Lets look at each one with examples.

#### 1. Function assigned to a variable 
```javascript
// Function assigned to a variable
let fullName = function(fname, lname){
    return (`${fname}${lname}`);
}
fullName();
```
In the above code a unnamed function is assigned to a variable "fullName". We can invoke the function by calling fullName();


#### 2. Function passed as argument to another function
```javascript
// Function passed as argument to another function
let fullName = function(fname, lname){
    return (`${fname}${lname}`);
}

function createEmail(fn,ln, fun1){
    let full_name = fun1(fn,ln);
    return ${full_name}@gmail.com`;
}
let pass = createEmail("kiran", "raj",fullName)
```
In the above example function "FullName" is passed as parameter to "createEmail" function.


#### 3. Function return another function
```javascript
// Function return another function
function calc(x,y, fun1, fun2){
    let r1 = fun1(x,y);
    let r2 = fun2(x,y);
    console.log(`${x} * ${y} = ${r1}`);
    console.log(`${x} / ${y} = ${r2}`);
    return function() {
        console.log(`${x} + ${y} = ${x + y}`);
        console.log(`${x} - ${y} = ${x - y}`);
    }
}

calc(20,10, multiply, divide)();
// 20 * 10 = 200
// 20 / 10 = 2
// 20 + 10 = 30
// 20 - 10 = 10
```
In the above function function calc returns a function, the returned function can be called using double invocation.


#### 4. Function passed as value of object property 
```javascript
// Function passed as value of object property 
let admin1 = {
    fname: "kiran",
    lname: "raj",
    greetAdmin : function(){
        console.log(`Hello ${this. fname} ${this.lname}`);
    }
}
```
In the above code a unnamed method is passed as a value of object property, "greetAdmin". It can be invoked by calling admin1.greetAdmin().


#### 5. Function passed as array element
```javascript
// Function passed as array element
const divide = function(x,y){ return x/y; };
const multiply = function(x,y){ return x*y; };
const add = function(x,y){ return x + y; };
const substract = function(x,y){ return x - y; };

let calc_arr = [divide, multiply, add, substract];

console.log(calc_arr[0](10,20));    // 0.5
console.log(calc_arr[1](10,20));    // 200
console.log(calc_arr[2](10,20));    // 30
console.log(calc_arr[3](10,20));    // -10
```

### Higher-order functions in JavaScript
1. Array.prototype.map
2. Array.prototype.filter
3. Array.prototype.reduce
4. Array.prototype.forEach
5. Array.prototype.every
6. Array.prototype.some


### Array.prototype.map
*returns a new array with the results of callback applied to every element*

Map method creates a new array with result of invoking the callback once for each element of the array, in the order of the array. A new array is returned, there will be no change to the original array. The map() method takes a function as argument, the function has three arguments currentValue, index and array. The function will not be called for deleted indexes and indexes not set. Any element added to the array after first invocation of the callback will be ignored.

```javascript
// Syntax

arr.map(callback(currentVal, index ,array) {
                   // code to execute
}),thisArg;
```

*arr* represent the array in which the map is called, callback is called for every element of *arr*. *index*, *array*, and *thisArg* are all optional. *Index* refers to the index of the current element being passed to the callback, *array* represent the array in which map is called and *thisArg*, the value to be used for "this" when executing the callback. If "thisArg" is not provided "this" will be set to "undefined".

```javascript
let arr1 = [2,4,6,8,11,5];
let arr_map = arr1.map( elem => elem*elem);
console.log(arr_map);   //[4, 16, 36, 64, 121, 25]
console.log(arr1);      //[2, 4, 6, 8, 11, 5]
```
In the above code a new array "arr_map" is returned with square of the elements of arr1 using the map method. The equivalent code of the above is given below.

```javascript
let arr1 = [2,4,6,8,11,5];
let arr_map = [];
for (i =0; i< arr1.length; i++){
    arr_map.push(arr1[i]*arr1[i]);
}
console.log(arr_map)   //[4, 16, 36, 64, 121, 25]
console.log(arr1);     //[2, 4, 6, 8, 11, 5]
```
Higher-order functions are easy to implement and less number of statements.

```javascript
let arr1 = [2,4,6,8,11,5];
let arr2_map = arr1.map((elem, index, a) => {
    console.log(`Element ${elem} Index ${index} Array ${a}`);
    //  Element 2 Index 0 Array 2,4,6,8,11,5
    //  Element 4 Index 1 Array 2,4,6,8,11,5
    //  Element 6 Index 2 Array 2,4,6,8,11,5
    //  Element 8 Index 3 Array 2,4,6,8,11,5
    //  Element 11 Index 4 Array 2,4,6,8,11,5
    //  Element 5 Index 5 Array 2,4,6,8,11,5
});
```
Lets look at one more example.
```javascript
var names = ["kiran", "vishnu", "manu", "varun", "adi"];
let names_cap = names.map((index)=>{
    return index.charAt(0).toUpperCase()+ index.slice(1);
})

console.log(names_cap); 
//["Kiran", "Vishnu", "Manu", "Varun", "Adi"]
```
[Higher-order Functions Part-2](https://dev.to/kiranrajvjd/javascript-higher-order-functions-part-2-6bp)
[Higher-order Functions Part-3](https://dev.to/kiranrajvjd/javascript-higher-order-functions-part-3-4p9d)