All topics
Functionsintermediate

Higher-Order Functions

Functions that take other functions as arguments, return functions, or both — the foundation of functional-style JavaScript.

A higher-order function is any function that operates on other functions, either by accepting them as arguments or by returning a new function (or both). This concept is central to idiomatic modern JavaScript, and it's the theoretical backbone behind array methods like map, filter, and reduce, event handlers, and middleware patterns, so interviewers use it to test whether you think in terms of composable, reusable behavior.

A higher-order function is like a manager who doesn't do the specific task themselves but hands it off to whichever specialist (function) you give them — the manager (map/filter/reduce) still coordinates iterating over the whole team, but the actual per-item decision is entirely up to whichever specialist you plugged in.

Key Concepts

1
The reason higher-order functions are so powerful is that in JavaScript, functions are first-class values — they can be assigned to variables, stored in arrays or objects, passed as arguments, and returned from other functions, exactly like any other value type. This is what allows you to write a generic applyDiscount(items, discountFn) function where discountFn can be swapped out for any pricing strategy without rewriting applyDiscount itself.
applyDiscount(items, discountFn)discountFnapplyDiscount
2
Array methods are the most common everyday example: array.map(fn) applies fn to every element and returns a new array of results, array.filter(fn) keeps only elements where fn returns truthy, and array.reduce(fn, initial) accumulates a single value by repeatedly calling fn with an accumulator and each element. All three take a function as an argument and abstract away the manual looping, letting you describe *what* transformation you want rather than *how* to iterate.
array.map(fn)fnarray.filter(fn)array.reduce(fn, initial)
3
Functions that return functions are equally important: they enable currying (transforming a function that takes multiple arguments into a sequence of functions each taking one argument), decorators/wrappers (like a withLogging(fn) that returns a new function logging every call to fn), and factory functions that produce customized functions based on configuration. Mastering higher-order functions is largely about getting comfortable treating behavior itself as data you can pass around.
withLogging(fn)fn