Higher-order Functions

Published: Wednesday, May 25, 2022

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:

  1. Takes one or more functions as arguments
  2. 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.

javascript
Copied! ⭐️
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.

javascript
Copied! ⭐️
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:

javascript
Copied! ⭐️
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:

javascript
Copied! ⭐️
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.

javascript
Copied! ⭐️
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.

javascript
Copied! ⭐️
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!

javascript
Copied! ⭐️
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.

javascript
Copied! ⭐️
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 🙂.

Resources