Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.
This is the main contrast to first-order functions. First-order functions DO NOT take functions either as arguments or returning them as output.
The main goal of having higher-order functions is abstraction, that is, hiding certain gritty details of problem-solving allowing developers to focus on a few concepts at a time.
For example:
When using the .map()
higher-order function, our focus is not on how the function iterates through each of the array elements and passing these elements to the callback function. This level of problem-solving is abstract/hidden from us. Our concern then goes to: given an array, how do we want to transform it, without worrying about the specifics of iterating through each of the elements.
Writing higher-order functions
Even though JavaScript already supports several higher-order functions. Writing our own higher-order functions is still required from time to time.
So, say we are to write our own version of map()
function similar to what array.map()
does:
function map(arr, func){
let newArr = [];
for(let i=0; i<arr.length; i++){
newElem = func(arr[i]);
newArr.push(newElem);
}
return newArr;
}
let test = map([1, 2, 3],(val) => {return val * 2});
console.log(test); /* [2, 4, 6] */
Explanation of the map()
function code above:
function
map(arr, func)
takes two arguments: the array to be modified (arr
) and the function that modifies each of the array elements (func
).newArr
is the modified array that will be returned bymap
function.- using
for
loop, we iterate through each of thearr
elements. - Each
arr
element is passed to the callback function which modifies the specific element passed to it and returns it to the variable namednewElem
. - Now
newElem
is the modified new element returned by the callback function, and this value is then pushed to thenewArr
. - And finally the
map
function returnsnewArr
.
.map(), .filter(), .reduce()
.map
.filter
.reduce
are some examples of higher-order functions supported by JavaScript
a. Transforming Arrays with .map()
.map()
method transforms an array by putting each element through a given callback function.
syntax: array.map( callback( currentValue, currentIndex, array));
.map()
method returns a 'new' array with the results of the callback function applied to every element of the original array, in the same order.
b. Filtering Arrays with .filter()
.filter()
method returns a 'new' array containing only the elements that pass the condition specified in the given callback function.
syntax: array.filter( callback( currentValue, currentIndex, array));
c. Summarizing with .reduce()
.reduce
method reduces/ summarizes the whole array into a single value.
It does this by repeatedly taking the currentValue
from the array and combining it with the accumulator
.
syntax: array.reduce ( callback( accumulator, currentValue, currentIndex, array));
The code below, illustrates the use of .map()
, .filter()
and .reduce()
:
const persons = [
{name: 'Peter', birthYear: 1995},
{name: 'Mark', birthYear: 1992 },
{name: 'John', birthYear: 1991 },
{name: 'Jane', birthYear: 2000 },
{name: 'Tony', birthYear: 1990}
];
/*array.map
adds a third key-value pair-> age: 30, to each of the array elements.*/
persons.map(element => element.age = 2020 - element.birthYear);
console.log(persons);
/*array.filter
filters the elements with the property age less than or equal to 25*/
let persons_25 = persons.filter(element => element.age <= 25);
console.log(persons_25);
/*array.reduce
calculates the total age of persons. Sums the age property to a single value*/
let totalAge = persons.reduce((accumulator, element)=>accumulator + element.age, 0);
console.log(totalAge);
In conclusion, higher-order functions allow us to attain abstraction, hide the gritty details, and focus on a few essential concepts at a time.
Any comments and additions, would love to hear those.