Menu
Try in Playground

JavaScript Higher-Order Functions: map, filter, reduce & Callbacks

Higher-order functions in JavaScript — passing functions as arguments, returning them from other functions, and the map/filter/reduce patterns you'll use every day.

Functions Are Values

In JavaScript, a function is a value like any other. You can store it in a variable, put it in an array, pass it to another function, or return it from one. That fact alone unlocks a whole style of programming:

index.js
Output
Click Run to see the output here.

Once you're comfortable treating functions as values, higher-order functions stop feeling mysterious. A higher-order function is just a function that either takes a function as an argument, returns a function, or both. That's the whole definition.

Taking a Function as an Argument

The most common form: a function that accepts a callback and runs it for you. You've already used these without thinking about it.

index.js
Output
Click Run to see the output here.

forEach is higher-order — it takes your function and calls it once per item. setTimeout is higher-order — it takes your function and calls it after a delay. You focus on what to do; they handle when and how many times.

Writing your own looks the same. Here's a tiny function that runs a callback only if a condition is true:

index.js
Output
Click Run to see the output here.

action is a parameter that happens to hold a function. Calling it with action() runs whatever was passed in.

The Three You'll Actually Use: map, filter, reduce

Arrays come with higher-order methods that replace most of the for loops you'd otherwise write. Learn these three and a huge amount of everyday code gets shorter and clearer.

map — transform every item

index.js
Output
Click Run to see the output here.

map calls your function once per item and collects the return values into a new array. Same length, transformed contents. The original array isn't modified.

filter — keep the ones that match

index.js
Output
Click Run to see the output here.

filter keeps items where the callback returns truthy and drops the rest. Return value is a new array, possibly shorter.

reduce — fold the array into one value

index.js
Output
Click Run to see the output here.

reduce is the general-purpose one. The callback receives the running accumulator and the current item; whatever you return becomes the next accumulator. The second argument (0 here) is the starting value.

You can chain them. This is where the style pays off:

index.js
Output
Click Run to see the output here.

Read it top to bottom: keep paid orders, pull out the price, sum them up. No loop, no mutable counter, no off-by-one to worry about.

Returning a Function From a Function

The other half of higher-order. A function that builds and returns another function:

index.js
Output
Click Run to see the output here.

multiplyBy(2) runs once and hands back a brand-new function. That new function still remembers factor — that's a closure, and it gets its own page later. For now, the takeaway: calling multiplyBy with different arguments gives you different specialised functions built from the same template.

This pattern shows up everywhere:

index.js
Output
Click Run to see the output here.

One definition, two reusable functions. Beats writing warn and info by hand and keeping them in sync.

Named Functions vs Inline Callbacks

You can pass an inline arrow function, or pass a function by name. Both work — pick whichever reads better:

index.js
Output
Click Run to see the output here.

When you pass isEven (no parentheses), you're handing over the function itself. Adding () would call it immediately and pass the result — a common beginner mistake:

nums.filter(isEven);     // correct: passes the function
nums.filter(isEven());   // wrong: calls isEven with no args, passes the result

If the callback starts to sprawl past a couple of lines, pull it out and give it a name. The surrounding code usually reads better for it.

A Worked Example

Higher-order functions shine when you compose small pieces. Suppose you've got a list of products and want the names of affordable, in-stock items, uppercased:

index.js
Output
Click Run to see the output here.

Each helper has one job. Each array method does one transformation. The pipeline reads like a specification of what you want, not a description of how to loop.

When Not to Reach for Them

Higher-order methods are great — but they're not a loop replacement for every situation:

  • If you need to stop partway through, for or for...of with a break is clearer than trying to bail out of forEach.
  • If you're doing something async inside the callback, map and forEach won't await it. Use for...of with await, or Promise.all with map.
  • If the callback is mutating shared state, you're drifting away from the style's strengths. Reach for a plain loop or refactor to return new values.

Used where they fit, map, filter, and reduce cut most of the loop boilerplate out of everyday code. Used everywhere, they start to hurt readability. Pick the tool that makes intent clearest.

Next: Objects

Functions aren't the only values worth building on. Objects are JavaScript's workhorse for grouping related data and behavior together — and they're what most of the arrays you just filtered and mapped were full of. That's the next page.

Frequently Asked Questions

What is a higher-order function in JavaScript?

A higher-order function is a function that does at least one of two things: takes another function as an argument, or returns a function as its result. Array.prototype.map, setTimeout, and addEventListener are all higher-order — they accept a callback and run it for you.

What's the difference between map, filter, and reduce?

map transforms each item and returns a new array of the same length. filter keeps items where the callback returns truthy and returns a (possibly shorter) array. reduce folds the array into a single value by combining items one at a time. All three are higher-order functions that take a callback.

Why would you return a function from another function?

To build small, configurable helpers without repeating logic. A function like multiplyBy(n) returns a new function that multiplies by n, so multiplyBy(2) and multiplyBy(10) give you two specialised functions from one definition. This pattern uses closures and is common in event handlers, middleware, and utility libraries.

Learn to code with Coddy

GET STARTED