Higher Order Functions in JavaScript

Trending 5 months ago

How to Pass a Function arsenic an Argument to Another function.

Passing functions arsenic arguments to different functions is 1 of nan ways to customize nan behaviour of functions. It allows you to walk different functions arsenic parameters to a azygous function, making your codification cleaner and reusable. Let’s look astatine really we tin do that.

Example 1

Consider nan calculate() function, which helps america execute different mathematical calculations. It takes 2 numbers, a and b, and an cognition usability arsenic arguments. We past specify nan different mathematical functions, i.e., add, and  subtract.

We past usage nan calculate() usability pinch immoderate of nan mathematical functions and supply nan integers connected which nan mathematical operations will beryllium performed.

1 function calculate(a, b, operation) {
2 return operation(a,b);
3 }
4
5
6 function add(a, b) {
7 return a + b;
8 }
9
10 function subtract(a, b) {
11 return a - b;
12 }
13
14
15 console.log(calculate(10, 5, add)); //output // 15
16 console.log(calculate(10, 5, subtract)); //output //5

As you tin spot above, by separating nan different operations, our codification tin beryllium easy extensible without changing nan cipher () function.

Example 2

Let’s look astatine different example. Suppose you person nan array of names shown below;

1 const names = ['Ann','Alex', 'Barman', 'zen','liz', 'Christopher', 'Isabella']

Then suppose you were tasked pinch filtering retired nan group whose names person 3 characters aliases less; you would astir apt travel up pinch thing for illustration this:

1 function shortNames(namesArr){
2 const result = []
3 for(i=0; i< namesArr.length; i++){
4 if (namesArr[i].length <= 3){
5 result.push(namesArr[i])
6
7 }
8 }
9 return result
10 }
11
12 console.log(shortNames(names)) //output //[ 'Ann', 'zen', 'Liz' ]

Here, we create a usability shortNames, which takes an array of names arsenic a parameter. Then, we defined an quiet array called result. Then, we create a for loop, which loops done each constituent successful nan array and checks its length. If nan magnitude of an constituent is little than aliases adjacent to 3 characters, nan constituent is considered a short sanction and pushed to nan consequence array. Finally, we return nan caller array containing nan filtered short names.

Suppose we besides request to get each nan group pinch agelong names, i.e., names pinch 8 aliases much characters; our usability would look akin to nan shortNames() function

1 function LongNames(namesArr){
2 const result = []
3 for(i=0; i< namesArr.length; i++){
4 if (namesArr[i].length >= 8){
5 result.push(namesArr[i])
6
7 }
8 }
9 return result
10 }
11 console.log(LongNames(names)); //ouput // [ 'Christopher', 'Isabella' ]

The LongNames and shortNames functions some execute akin tasks, specified as:

  • looping done nan names array
  • filtering each sanction successful nan array based connected nan specified condition
  • pushing elements that fulfill nan information to a caller array

However, we tin shorten our codification and debar repetitive tasks by creating a communal function. Since we don’t request each nan logic successful our 2 functions above, we tin rewrite them arsenic shown below.

1 function isShortName(name, length) {
2 return name.length <= length;
3 }
4
5 function isLongName(name, length) {
6 return name.length >= length;
7 }

Here, we specify our functions isShortName and isLongName, which return 2 arguments: sanction and length. isShortName will cheque if nan fixed sanction is little than aliases adjacent to nan specified length. It returns existent if nan fixed sanction satisfies nan condition. 

IsLongName() does thing akin but returns existent if nan fixed sanction is much than aliases adjacent to nan provided length.

Next, we will create a filterNames usability to select names based connected different conditions. The filterNames usability will return 3 arguments:

  • names array.
  • The callback function(can either be  IsLongName aliases isShortName).
  • The magnitude information utilized to select nan names.
1 function filterNames(namesArr, conditionFn, length) {
2 const result = [];
3 for (let i = 0; i < namesArr.length; i++) {
4 if (conditionFn(namesArr[i], length)) {
5 result.push(namesArr[i]);
6 }
7 }
8 return result;
9 }

So now if we determine to usage nan filterNames()  pinch immoderate of nan callback functions, we will get nan aforesaid output.

1 console.log(filterNames(names, isShortName, 3)); // [ 'Ann', 'zen', 'Liz' ]
2 console.log(filterNames(names, isLongName, 8)); //[ 'Christopher', 'Isabella' ]

Examples of Higher Order Functions

Higher-order functions are commonly utilized for mapping, filtering, and reducing arrays. The astir commonly utilized higher-order functions include:

  • filter() 
  • map()
  • reduce()

Using nan filter() method

As nan sanction suggests, nan filter() method filters elements connected an array based connected nan specified condition. When applied to an array, nan filter() method will create different array pinch only nan elements from nan original array that fulfill nan information successful nan function.

Consider nan array below, which consists of nan names and salaries of immoderate employees.

1 const employees = [
2 {name: "Alice",salary: 25000 },
3 {name: "Bob",salary: 30000},
4 {name: "Charlie",salary: 28000},
5 {name: "Cate",salary: 100000,},
6 {name: "Mike",salary: 120000,},
7 {name: "Lucy",salary: 55000,},
8 {name: "Liam",salary: 70000,},
9 ]

Suppose we want to select retired nan labor earning much than 70,000. One measurement to do this would beryllium utilizing a for loop, loop complete each constituent and, pinch each iteration, push nan worker that satisfies our information to a caller array, arsenic shown below.

1 const filteredEmployees = []
2 for(i =0 ;i <employees.length; i++){
3 if(employees[i].salary >=70000 ){
4 filteredEmployees.push(employees[i])
5 }}
6
7 console.log(filteredEmployees);

Even though nan usability useful arsenic expected, location are amended ways to instrumentality nan solution. The select () method is an fantabulous solution to our problem. Its syntax looks for illustration this;

1 const newArray = array.filter(callbackFn,thisArg)

Where callbackFn is nan usability for filtering elements. The callbackFn takes 3 optional arguments: element, index, and array.  thisArg is optional.

Let’s first specify nan callbackFn, which will return successful an worker entity and cheque if nan worth successful nan net spot is much than 70,000.

1 function checkSalary(employee){
2 return employee.salary >= 70000
3 }

Next, let’s use nan filter() method to our callbackFxn and delegate it to nan filtredArray.

1 const filteredArray = employees.filter(checkSalary);
2 console.log(filteredArray)

Our output will look for illustration this:

1 [
2 { name: 'Cate', salary: 100000 },
3 { name: 'Mike', salary: 120000 },
4 { name: 'Liam', salary: 70000 }
5 ]

Using nan Map() Method

The map() method is different higher-order usability which creates a caller array by applying a callback usability to each constituent connected nan original array.

The syntax looks for illustration this:

1 const newArray = originalArray.map(callbackFn, thisArg);

where nan callbackFn takes successful nan pursuing parameters, 

  • currentValue - nan existent constituent being processed
  • index - nan scale of nan existent constituent being processed
  • array -the original array 

thisArg is optional.

Given nan students array below, which contains students’ names and grades for different subjects and wide grades, we want to extract conscionable nan names and wide grades from nan array.

1 const students = [
2 {
3 names: "Alice Bob",Math: 85,Science: 92,History: 78,English: 88,Art: 95,
4 grade:87.6
5 },
6 {
7 names: "Michael Smith",Math: 76,Science: 89,History: 92,English: 80,
8 Art: 91,
9 grade:85.6
10 },
11 {
12 names: "William Brown",Math: 70,Science: 78,History: 75,English: 88,Art: 79,
13 grade:76
14 },
15 {
16 names: "Julia Lee", Math: 52, Science: 63, History: 76, English: 87,
17 Art: 94,
18 grade:74.2
19 },
20 {
21 names:"George Harrison",Math: 88,Science: 77,History: 50,English: 84,
22 Art: 71,
23 grade:74
24 },
25 ];

We tin usage nan map() method to retrieve nan student names and wide grades. First, let’s create nan callback function, which takes a student arsenic an statement and extracts nan student’s sanction and nan wide grade.

1 function gradeOnly(student){
2 return ({names:student.names, grade: student.grade})
3 }

Our callback usability will return a student entity arsenic an statement and return a caller entity containing only nan names and people properties. 

Next, we will usage nan map() method to create a caller array by applying nan gradeOnly() to each student successful nan students array.  The map() method will iterate done each student array constituent and use nan gradeOnly() function. 

1 const studentsData = students.map(gradeOnly)
2 console.log(studentsData)

Our output will be:

1 [
2 { names: 'Alice Bob', grade: 87.6 },
3 { names: 'Michael Smith', grade: 85.6 },
4 { names: 'William Brown', grade: 76 },
5 { names: 'Julia Lee', grade: 74.2 },
6 { names: 'George Harrison', grade: 74 }
7 ]

Using arrow functions, we tin simplify this look arsenic follows:

1 const studentsData = students.map(
2 student=> ({names:student.names, grade: student.grade}))
3 console.log(studentsData)

Using Array.reduce() Method

As nan sanction suggests, nan reduce() method takes successful an array and reduces it to a azygous value. The syntax for nan trim method looks for illustration this.

1 array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

where

  • The full will beryllium nan result
  • the currentValue will beryllium nan existent constituent during nan loop process
  • The initialValue will beryllium 0
  • currentIndex and arr are optional 

Suppose you wanted to find retired nan sum of numbers successful nan numbers array beneath utilizing nan reduce() method:

1 numbers = [10,20,30,40]

Let’s commencement by defining nan callback usability that will return successful nan full and number arsenic arguments. The callback usability will return nan consequence of adding each number successful our original array to nan total. 

1 function addNumbers(total,number){
2 return total+=number
3 }

Next, use nan reduce() method to nan numbers array and usage nan addNumbers arsenic nan callback function. Each constituent successful nan numbers array is applied to nan callback usability for each iteration.

1 const cumulativeTotal =numbers.reduce(addNumbers);
2 console.log(cumulativeTotal); //output //100

The output will beryllium 100, arsenic expected.  If we don’t specify an first value, nan first constituent will beryllium considered nan first value, and nan output will still beryllium nan same.

1 numbers = [10,20,30,40]
2 numbers.reduce(function(total, number){
3 return total+number
4 })

We tin further shorten our look utilizing arrow functions arsenic follows:

1 const cumulativeTotal = numbers.reduce((total,number) => total+=number)
2 console.log(cumulativeTotal); //output //100

Benefits of Higher Order Functions

  • Higher-order functions absurd nan underlying logic required for performing tasks. For example, erstwhile we utilized nan reduce() method, we abstracted nan underlying logic of iterating done each element, adding it to nan total, and returning nan result. We didn't request to constitute nan loop and accumulation logic explicitly; nan trim usability handled it for us.
  • Utilizing higher-order functions enhances codification readability and maintainability compared to implementing nan aforesaid functionality pinch loops.
  • Higher-order functions besides make your codification reusable.

Up Your JS Game With Tuts+

Conclusion

This tutorial introduced you to higher-order functions and offered applicable examples and scenarios wherever they tin beryllium applied to JavaScript programming. Incorporating higher-order functions into your improvement practices tin importantly heighten your skills arsenic a JavaScript developer.

More
Source Tuts Plus
Tuts Plus