JavaScript Higher-Order Functions

Functions That Take or Return Functions

JavaScript Higher-Order Functions

In JavaScript, functions are values. You can pass them as arguments and return them from other functions — the foundation of `map`, `filter`, and composition.

5 min read Level 3/5 #higher-order#functions#callbacks
What you'll learn
  • Pass functions as arguments
  • Return functions from functions
  • Compose small functions into bigger behavior

In JavaScript, functions are first-class values. You can:

  • Store them in variables
  • Pass them as arguments
  • Return them from other functions
  • Put them in arrays and objects

A higher-order function is one that takes another function as an argument, or returns a function, or both.

Functions as Arguments — Callbacks

You’ve been using higher-order functions since the Array Iteration chapter — map, filter, reduce, forEach. They all take a function as their argument.

Built-in higher-order functions script.js
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map((n) => n * 2);
const evens = numbers.filter((n) => n % 2 === 0);
const total = numbers.reduce((sum, n) => sum + n, 0);

console.log(doubled); // [2, 4, 6, 8, 10]
console.log(evens);   // [2, 4]
console.log(total);   // 15
▶ Preview: console

The function you pass is called a callback — you “call it back” later, inside the higher-order function.

Writing Your Own

A function that uses a callback to decide what to do:

A custom higher-order function script.js
function repeat(times, callback) {
  for (let i = 0; i < times; i++) {
    callback(i);
  }
}

repeat(3, (i) => console.log(`step ${i}`));
// "step 0"
// "step 1"
// "step 2"
▶ Preview: console

Functions That Return Functions

A function can return another function. This is the basis of factories, partial application, and composition.

A function factory script.js
function makeMultiplier(factor) {
  return (n) => n * factor;
}

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

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

makeMultiplier takes a number and returns a new function tailored to multiply by that number. The returned function closes over factor.

Composition

When you have small functions that each do one thing, you can compose them — chain them so the output of one feeds the input of the next.

compose two functions script.js
const compose = (f, g) => (x) => f(g(x));

const trim = (s) => s.trim();
const lower = (s) => s.toLowerCase();

const normalize = compose(lower, trim);

console.log(normalize("  Hello World  "));
// "hello world"
▶ Preview: console

Reading right to left: trim runs first, then lower runs on the result. Small, focused functions compose into bigger behavior — a pattern from functional programming that JavaScript inherits.

Real-World Patterns

Custom filters

A composable filter script.js
const isAdult = (user) => user.age >= 18;
const isAdmin = (user) => user.role === "admin";

const users = [
  { name: "Ada", age: 36, role: "admin" },
  { name: "Tim", age: 12, role: "user" },
  { name: "Lin", age: 28, role: "user" },
];

console.log(users.filter(isAdult));            // Ada, Lin
console.log(users.filter(isAdmin));            // Ada
console.log(users.filter((u) => isAdult(u) && isAdmin(u))); // Ada
▶ Preview: console

Throttling, debouncing, caching

Higher-order functions are how you wrap behavior around other functions — “call this at most once per second”, “cache results”, “log every call”. You’ll see these patterns when we build real apps.

Try It Yourself

Exercise

Compose two functions

Difficulty 3/5~3 min
Write `compose(f, g)` — a function that takes two functions and returns a new function that, given `x`, returns `f(g(x))` (`g` first, then `f`). Verify with these helpers: ``` const trim = (s) => s.trim(); const upper = (s) => s.toUpperCase(); const normalize = compose(upper, trim); console.log(normalize(" hi ")); // "HI" ```
solution.js
// declare compose here

const trim  = (s) => s.trim();
const upper = (s) => s.toUpperCase();
const normalize = compose(upper, trim);
console.log(normalize("  hi  "));
3tests will run
💡 Show hint
`function compose(f, g) { return (x) => f(g(x)); }`
✅ Show solution
function compose(f, g) {
  return (x) => f(g(x));
}

const trim  = (s) => s.trim();
const upper = (s) => s.toUpperCase();
const normalize = compose(upper, trim);
console.log(normalize("  hi  "));

End of Chapter

Functions are the unit of abstraction in JavaScript. Next chapter: objects and classes — the unit of structure.

Next chapter: Objects & Classes →