Home/Blog/JavaScript/Higher-Order Functions in JavaScript
Higher-Order Functions in JavaScript
JavaScript7 min readSep 22, 2026

Higher-Order Functions in JavaScript

Higher-order functions are one of the most important ideas in JavaScript, and you're probably already using them without realizing it. This blog explains what makes a function "higher-order," why they matter, and how methods like map, filter, and setTimeout all rely on this same simple idea.

452 views0 likes0 comments0 bookmarks

If you've ever used .map(), .filter(), setTimeout(), or addEventListener(), you've already used a higher-order function. You just didn't know it had a name.

That's actually good news. It means this concept isn't some advanced, hard-to-reach idea. It's something you already use every day. This blog just gives it a name, explains why it works, and shows you how to write your own.

box-labled-higher-order-function.png

What is a higher-order function?

A higher-order function is simply a function that does at least one of these two things:

  • It takes another function as one of its inputs, or

  • It returns a function as its result

That's the whole definition. Nothing more complicated than that. Any function that does either of these things is called "higher-order," and any function that does neither is called a regular, or "first-order," function.

This is only possible in JavaScript because of one core idea: functions are values. In JavaScript, a function isn't some special, separate thing. It can be stored in a variable, passed around, and used just like a number or a string can be.

js

Js
const greet = function () {
  console.log("Hello!");
};

console.log(typeof greet); // "function"

Because functions are just values, you can pass them into other functions, the same way you'd pass in a number or a string. That one idea is the entire foundation of higher-order functions.

A function that takes another function

Here's a simple example. We'll write a function called repeat that runs another function a certain number of times.

js

Js
function repeat(times, action) {
  for (let i = 0; i < times; i++) {
    action(i);
  }
}

repeat(3, function (i) {
  console.log("Running number " + i);
});

// Output:
// Running number 0
// Running number 1
// Running number 2

repeat is a higher-order function because it takes action as an input, and action is itself a function. Every time the loop runs, repeat calls action, passing in the current number. The function we pass in decides what actually happens on each run. repeat doesn't care what action does, it just knows when to call it.

This is a powerful idea. repeat can be reused for anything, not just logging numbers.

js

Js
repeat(3, function (i) {
  console.log("Item " + i + " added to cart");
});

Same repeat function, completely different behavior, just by passing in a different function.

A function that returns another function

Now let's look at the second kind of higher-order function, one that returns a function instead of taking one in.

js

Js
function multiplyBy(factor) {
  return function (number) {
    return number * factor;
  };
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

multiplyBy is higher-order because it returns a brand new function every time you call it. double and triple are both functions created by multiplyBy, each one remembering a different value for factor. This works because of closures, something we covered in detail in our Closures in JavaScript post, if you want to understand exactly why double and triple remember their own separate factor values.

The built-in higher-order functions you already use

JavaScript comes with several higher-order functions built right in, and you've almost certainly used them already.

map, filter, and reduce all take a function as an input, and use it to decide what to do with each item in an array. We covered these in detail in our Array Methods guide, and now you know the proper name for why they work the way they do: they're all higher-order functions.

js

Js
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map(function (num) {
  return num * 2;
});

setTimeout takes a function and runs it later, after a certain amount of time.

js

Js
setTimeout(function () {
  console.log("This runs after 2 seconds");
}, 2000);

addEventListener takes a function and runs it whenever a specific event happens, like a click or a key press.

js

Js
button.addEventListener("click", function () {
  console.log("Button was clicked");
});

In every one of these examples, you're handing a function to another function, and trusting it to call your function at the right time. That's the higher-order function pattern, showing up everywhere in JavaScript, whether you noticed it or not.

[IMAGE: A dark background diagram showing four labeled boxes in a row - map, filter, setTimeout, addEventListener - each with a small arrow pointing into it labeled "your function goes in here", showing the same shared pattern across all four]

Why do higher-order functions actually matter?

The real benefit is reusability. Without higher-order functions, you'd have to write a new, slightly different loop or a new block of logic every single time you needed to do something similar. With higher-order functions, you write the repeating structure once, like repeat, or like map, and then just plug in different functions to change what actually happens each time.

This also makes code easier to read. Seeing numbers.filter(isEven) immediately tells you what's happening, filtering numbers using some rule called isEven, without needing to read a full loop to figure that out.

Writing your own higher-order function

Let's write one more practical example, a function that adds simple logging around any other function, without changing that function itself.

js

Js
function withLogging(fn) {
  return function (...args) {
    console.log("Calling function with:", args);
    const result = fn(...args);
    console.log("Result:", result);
    return result;
  };
}

function add(a, b) {
  return a + b;
}

const loggedAdd = withLogging(add);

loggedAdd(3, 4);
// Logs: Calling function with: [3, 4]
// Logs: Result: 7

withLogging is higher-order in both ways at once. It takes a function (fn) as an input, and it also returns a brand new function. That returned function calls the original fn, but wraps some extra behavior around it, in this case, logging. Notice that add itself never had to change. We wrapped new behavior around it from the outside, which is one of the most useful things higher-order functions let you do.

Common mistakes beginners make

The most common mistake is calling the function instead of passing it. Writing repeat(3, action()) instead of repeat(3, action) runs action immediately and passes its result into repeat, instead of passing the function itself. Always pass the function by its name, without the parentheses, unless you're intentionally calling it right there.

The second common mistake is forgetting that a function returned by another function needs to actually be called to run. Writing const double = multiplyBy(2); and expecting double to already equal a number is a common early confusion. double is a function, not a number, so you still need to call double(5) to actually get a result.

Quick reference - what makes a function higher-order

Pattern

Example

What makes it higher-order

Takes a function as input

repeat(3, action)

The function passed in decides what happens

Returns a function

multiplyBy(2)

Creates a new, customized function each time

Built-in examples

map, filter, reduce, setTimeout, addEventListener

All accept a function you provide

Interview Questions

What is a higher-order function? A function that either takes another function as an argument, or returns a function as its result, or both. It's possible in JavaScript because functions are treated as values.

Give an example of a built-in higher-order function. map, filter, and reduce are all higher-order functions, since each one takes a function as an argument and uses it to decide what happens to each item in an array.

What's the difference between a higher-order function and a callback function? A callback is the function you pass in. A higher-order function is the function that accepts (or returns) that callback. map is a higher-order function, and the function you pass into .map() is the callback.

Why are higher-order functions useful? They let you reuse the same structure or loop while changing the actual behavior just by passing in a different function, which reduces repeated code and makes logic easier to read.

Can a function be higher-order without taking any arguments? Yes. If a function returns another function, like multiplyBy does, it's still higher-order, even if it doesn't take a function in as an argument.

Wrapping up

A higher-order function isn't a special or advanced feature you have to learn separately. It's just a natural result of functions being treated as values in JavaScript. Once you can spot the pattern, a function taking another function in, or handing one back out, you'll start noticing it everywhere, in the built-in methods you already use, and in your own code once you start writing it on purpose.

If you haven't already, our Callback Functions in JavaScript post pairs well with this one, since callbacks are simply the functions you pass into a higher-order function. And if you want to see the closure mechanics behind functions that return other functions, our Closures in JavaScript post covers that in detail.

Comments

Sign in to join the conversation

Related Articles

More insights you might enjoy

Async/Await in JavaScript - How It Actually Works and Why It Exists
Backend

Async/Await in JavaScript - How It Actually Works and Why It Exists

How async/await works in JavaScript - async functions, await, error handling, parallel vs sequential execution, and the most common mistakes explained.

Sadie Sink·12 min
1641
JavaScript Closures - The Concept Interviewers Actually Test
JavaScript

JavaScript Closures - The Concept Interviewers Actually Test

Closures are one of the most asked-about JavaScript concepts in interviews, and also one of the most misunderstood. This blog explains what a closure actually is, why functions can remember variables from outside their own scope, and where closures show up in real code

Vishal Vishwakarma·9 min
1231
React vs Next.js: What's Actually Different and When to Use Which

React vs Next.js: What's Actually Different and When to Use Which

React and Next.js are often confused - one is a UI library, the other is a full framework built on top of it. This post breaks down the real differences: rendering strategies, routing, API routes, and when to pick one over the other.

Sadie Sink·8 min
3570
How React's useEffect Actually Works - And Why Developers Misuse It

How React's useEffect Actually Works - And Why Developers Misuse It

useEffect is one of the most used hooks in React and also one of the most misunderstood. This guide covers the dependency array, cleanup functions, the double render, and common mistakes that cause bugs.

Sadie Sink·8 min
2850
Node.js and Express.js - What They Are, How They Differ, and How They Work Together

Node.js and Express.js - What They Are, How They Differ, and How They Work Together

Node.js and Express.js are not the same thing. This guide explains what each does, how they work together, and covers routing, middleware, and error handling with real code.

Sadie Sink·9 min
2640
How the JavaScript Event Loop Actually Works - A Deep Dive

How the JavaScript Event Loop Actually Works - A Deep Dive

A complete deep dive into the JavaScript event loop - the call stack, callback queue, microtask queue, and how they work together to make async JavaScript possible.

Sadie Sink·11 min
2510