What is a higher-order function?
First, a higher-order function is exactly what it means: a higher level of abstraction than a typical function. It is a function that performs operations on other functions. In this definition, an operation might mean taking one or more functions as arguments or returning a function as a result. You don’t have to do both at the same time. A feature is considered a higher-level feature by performing one or more operations.
The sample
If you don’t have a higher-order function and want to add 1 to each number in the array and display it in the console, you can do the following:
const numbers = [1.2.3.4.5];
function addOne(array) {
for (let i = 0; i < array.length; i++) {
console.log(array[i] + 1);
}
}
addOne(numbers);
Copy the code
The function addOne () in the code above takes an array, adds 1 and each number in the array, and displays it in the console. The original value remains unchanged in the array, but the function is doing something for each value in the array.
However, using the most common higher-order function forEach (), we can simplify the process:
const numbers = [1.2.3.4.5];
numbers.forEach((number) = > console.log(number + 1));
Copy the code
A: wow!
We have abstracted the function definition and call from the original code above into a single line!
We apply forEach() to an array named “numbers”. ForEach () begins with an anonymous function that takes one element of the array at a time. For arrays named numbers, it makes sense to name each element in the array “number,” although we could name it “Element” or “el,” or even “whatever.”
Next, the anonymous arrow function prints the value of the number + 1 to the console.
Similarly, the higher-order function forEach() applies the function to each element of the array.
Another higher-order function example
If there is no higher order function, if I want to create a new array with only odd numbers, I can do the following:
const numbers = [1.2.3.4.5];
function isOdd(array, oddArr = []) {
for (let i = 0; i < array.length; i++) {
if (array[i] % 2! = =0) { oddArr.push(array[i]); }}return oddArr;
}
const oddArray = isOdd(numbers);
console.log(oddArray);
Copy the code
In the above code, the function isOdd() takes an array and takes an optional second array parameter. If not provided, the array defaults to an empty array.
This function checks each number in the array to see if it is odd. If the number is odd, it is added to the array from the second parameter. After checking all the numbers, return the array of the second argument.
If you use the higher-order filter() function, you can write it like this:
const numbers = [1.2.3.4.5];
const oddArray = numbers.filter((number) = > number % 2! = =0);
console.log(oddArray);
Copy the code
🤩
Isn’t there a lot of simplification in the code?
The above code first defines a new array, oddArray, because applying filter() creates a new array. Higher-order functions return each element that meets the criteria set in the anonymous function. Again, the anonymous function is applied to each element in the numbers array.
Keep up the good work and draw inferences
So far, I think you’re starting to see why higher-order functions are so good!
Let’s look at another example…
Going back to our forEach() example, we add 1 to each number in the array and print each value to the console. But what if you use these new values to create a new array? Without higher-order functions, I can do this:
const numbers = [1.2.3.4.5];
function addOneMore(array, newArr = []) {
for (let i = 0; i < array.length; i++) {
newArr.push(array[i] + 1);
}
return newArr;
}
const newArray = addOneMore(numbers);
console.log(newArray);
Copy the code
The function addOneMore() in the above code again takes an array and takes the array as its second argument, which defaults to null. Add 1 to each element of the existing numbers array and push the result into the new array returned.
Now we use the higher-order function map() to abstract the above code:
const numbers = [1.2.3.4.5];
const newArray = numbers.map((number) = > number + 1);
console.log(numbers);
Copy the code
The above code defines newArray first, because map() creates a newArray. Like forEach(), map() applies an anonymous function to each element of the numbers array. However, map() creates a new array in the process.
further
What if we want to find the sum of all the values in the numbers array?
Without higher-order functions, I can do this:
const numbers = [1.2.3.4.5];
function getTotalValue(array) {
let total = 0;
for (let i = 0; i < array.length; i++) {
total += array[i];
}
return total;
}
const totalValue = getTotalValue(numbers);
console.log(totalValue);
Copy the code
The function getTotalValue() in the above code takes an array, defines the total variable to be equal to 0, and iterates through the array as each element is added to the total variable. Finally, it returns the total.
Now using the higher-order reduce() function, the process can be abstracted again:
const numbers = [1.2.3.4.5];
const totalValue = numbers.reduce((sum, number) = > sum + number);
console.log(totalValue);
Copy the code
The higher-order reduce() function in the above code takes two arguments in the internal anonymous function.
The first argument is the accumulator, and the second argument is the element in the numbers array.
The accumulator parameter (sum in the example above) keeps track of the total because reduce() applies anonymous functions to each element of the array.
conclusion
Higher-order functions provide a higher level of abstraction for functions. They have the potential to take your JavaScript code to new heights!