Higher-Order Functions
TL;DR
In JavaScript, functions are First-Class Citizens. This means functions are just regular objects. They can be assigned to variables, stored in arrays, passed as arguments, and returned from other functions.
A Higher-Order Function (HOF) is a function that does at least one of two things:
- Accepts another function as an argument (a Callback).
- Returns a new function.
Mental Model
How It Works
HOFs allow developers to abstract over actions, not just values.
Instead of writing a for loop that manually iterates over an array and does math, you pass a math function to Array.map(). map handles the iteration (the “how”), and your callback function handles the math (the “what”). This is the foundation of declarative programming.
Example
// 1. HOF that takes a function as an argument
function executeTwice(callback) {
callback();
callback();
}
executeTwice(() => console.log("Hello!")); // Prints Hello! twice.
// 2. HOF that returns a function
function createMultiplier(multiplier) {
return function(value) {
return value * multiplier;
};
}
const double = createMultiplier(2);
console.log(double(10)); // 20
Common Output Question
const numbers = [1, 2, 3];
const result = numbers.map(parseInt);
console.log(result);
Q: What is the output and why?
A: [1, NaN, NaN].
This is a classic trap. Array.map passes three arguments to its callback: (value, index, array).
parseInt expects two arguments: (string, radix).
So, map calls parseInt like this:
parseInt(1, 0)-> radix 0 defaults to base 10 ->1.parseInt(2, 1)-> radix 1 is invalid in math ->NaN.parseInt(3, 2)-> binary only allows 0 and 1. ‘3’ is invalid ->NaN.
(Fix:numbers.map(num => parseInt(num))).
Senior Interview Question
Q: Write a Higher-Order Function once(fn) that ensures a function can only be executed exactly one time, no matter how many times it is called.
A: This tests closures and HOFs together.
function once(fn) {
let hasRun = false;
let result;
return function(...args) {
if (!hasRun) {
result = fn.apply(this, args);
hasRun = true;
}
return result; // Return the cached result on subsequent calls
};
}
const initialize = once(() => console.log("DB Connected!"));
initialize(); // "DB Connected!"
initialize(); // Does nothing, returns undefined