Higher-order Functions
Greetings, friends! Have you ever been asked what a "higher-order function" is during an interview? It sounds complicated, but it's actually really simple. According to Wikipedia, a higher-order function is a function that does at least one of the following:
- Takes one or more functions as arguments
- Returns a function as its result
You may have seen examples of higher-order functions already. When we create functions that accept a callback function, it fulfills the first criterion of being a higher-order function.
function higherOrderFunction(callback) {
callback();
}
function logInfo() {
console.log('logging info...')
}
higherOrderFunction(logInfo);
// OUTPUT: logging info...
In my personal experience, it's more common to refer to functions as higher-order functions when the second criterion is fulfilled. That is, the function returns a function as its result. Let's look at an example.
function multiplyBy(multiple) {
return function multiplyValues(num) {
return multiple * num;
}
}
const double = multiplyBy(2);
const finalResult = double(3);
console.log(finalResult);
// OUTPUT: 6
In the code snippet above, we are creating a function called multiplyBy that returns another function. The inner function will then return the product of multiple and num.
We assign the result of multiplyBy(2) to the variable, double. This variable is now equal to the inner function but with multiple set to 2. Think of double being equal to the following:
const double = function multiplyValues(num) {
return 2 * num;
}
Next, we assign double(3) to the variable, finalResult. This variable is now equal to the product of multiple and sum. Think of finalResult being equal to the following:
const finalResult = multiplyValues(3) // return 2 * 3 = 6
When we log finalResult to the console, we obtain the product of 2 * 3 which equals 6. Do you see what happened? We assigned a function to a variable. Then, we deferred execution of our function until later. This pattern is very common in JavaScript.
Let's take a look at our example using arrow functions instead.
const multiplyBy = multiple => {
return (num) => {
return multiple * num;
}
}
const double = multiplyBy(2);
const finalResult = double(3);
console.log(finalResult);
// OUTPUT: 6
If we use a concise body for the arrow function, we can make the code even shorter.
const multiplyBy = multiple => num => multiple * num;
const double = multiplyBy(2);
const finalResult = double(3);
console.log(finalResult) // 6
But wait! There's more! If we remove the two variables, we can make this code even shorter!
const multiplyBy = multiple => num => multiple * num;
console.log(multiplyBy(2)(3)) // 6
Our code is tremendously cleaner now! Additionally, we can also create new functions out of our higher-order functions.
const multiplyBy = multiple => num => multiple * num;
const double = multiplyBy(2);
const triple = multiplyBy(3);
const quadruple = multiplyBy(4);
console.log(double(3)) // 6
console.log(triple(3)) // 9
console.log(quadruple(3)) // 12
I hope you see the power of higher-order functions now! Next time you're asked about them during an interview, I'm sure you'll be ready 🙂.