Callbacks & Higher-Order Functions
A Function That Takes a Function
You have already been doing this. Every time you wrote array.map(fn) or array.filter(fn), you passed a function as an argument. But you probably never stopped to ask: what exactly is happening there?
Start here — no arrays yet. Just a plain function receiving another function:
doTwice doesn't know or care what fn does. It just calls it. greet doesn't know it will be called twice. They are completely independent — connected only at the moment of the call.
A function that receives a function as an argument (or returns one) is called a higher-order function. The function passed in is called a callback.
The Key Insight: Functions Are Values
In JavaScript, a function is just a value — the same as a number or a string. You can store it in a variable, put it in an array, pass it to another function, return it from a function.
calculate is a general-purpose machine. The behaviour — what to actually do with the two numbers — is plugged in from outside. This is the fundamental shift in thinking: instead of hard-coding logic, you make it a parameter.
Writing Your Own map
Array.map is so useful that it's built into the language. But it's not magic — you could write it yourself:
myMap handles the iteration — the tedious mechanical part. You supply the interesting part: what to do with each element. This division of responsibility is the entire point of higher-order functions.
Writing Your Own filter
The loop doesn't change. The decision changes. You wrote one function that can filter by any criterion, ever.
Writing Your Own reduce
reduce is the most powerful of the three — and the most misunderstood. It collapses an entire array into a single value by repeatedly applying a callback.
reduce can produce anything — a number, a string, an array, an object. The callback decides what "combining" means. The accumulator starts as initial and grows with every element.
Chaining: map, filter, reduce Together
This is where it all comes together. Real data processing is a pipeline — filter out noise, transform what remains, combine into a result.
Each step in the chain does one thing. No intermediate variables. No mutation. The data flows through the pipeline and you get exactly what you need.
Functions That Return Functions (Revisited)
You saw this in closures. Now see it as a higher-order function pattern — creating specialised callbacks on demand:
above(70) doesn't filter — it creates a filter. You call it once, get a function back, and that function is passed to .filter. This pattern gives you reusable, readable, composable conditions.
Callbacks in the Wild: forEach and sort
forEach and sort are also higher-order functions — you just see them less analytically because they're so familiar.
The comparator callback (a, b) => b.marks - a.marks is a pure higher-order function interaction — sort calls your function repeatedly to decide the order, and you just define the rule.
A General-Purpose Pipeline
Once you understand higher-order functions, you can build tools that work on any data at all:
pipeline takes any number of functions and chains them left-to-right. Each function receives the output of the previous one. This is functional composition — a concept that scales from three functions to entire application architectures.
What You Have Learned
Higher-order functions are the mechanism that makes JavaScript's functional style possible.
The key ideas:
- A callback is a function passed to another function to be called later
- A higher-order function receives a function as an argument, returns one, or both
map,filter,reduceare higher-order functions — and you can write them yourself in a dozen lines- Chaining these three gives you a powerful, readable data-processing pipeline with no mutation
- Functions that return specialised callbacks (
above(70),makeMultiplier(3)) are the higher-order + closure pattern working together sortandforEachare also higher-order — their comparators and iteratees are callbacks
In the next lesson: Asynchronous JavaScript — timers, promises, and async/await. Everything you have learned about callbacks has been building to this. In async code, the callback isn't called immediately — it's called later, after something happens. Understanding that shift in time is what separates beginners from developers who can build real applications.