JavaScript Higher-Order Functions

A higher-order function is a function that either takes another function as an input, returns a function as its output, or does both. JavaScript treats functions as first-class citizens — you can store them in variables, pass them around, and return them just like numbers or strings.

Why the Name "Higher-Order"?

In mathematics, a function that operates on other functions is called higher-order. The concept carries into programming. A regular function works with data. A higher-order function works with other functions as if they were data.

Diagram: Regular vs Higher-Order Function

Regular Function:
  Input: numbers, strings, objects
  Output: numbers, strings, objects

Higher-Order Function:
  Input: numbers, strings, functions ◄── functions as input
  Output: numbers, strings, functions ◄── functions as output

Type 1: Functions That Accept a Function

The most common pattern. You pass a function as an argument, and the outer function uses it.

function runTwice(action) {
  action();
  action();
}

runTwice(function() {
  console.log("Hello!");
});

// Output:
// Hello!
// Hello!

runTwice is the higher-order function. It takes action (a function) and calls it twice.

Type 2: Functions That Return a Function

A higher-order function can create and return a new function. This is powerful because you can build customized functions on the fly.

function makeMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

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

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

Diagram: makeMultiplier Factory

makeMultiplier(2) ──► returns a function that multiplies by 2
                               │
                               ▼
                       double = fn(n) => n * 2

makeMultiplier(3) ──► returns a function that multiplies by 3
                               │
                               ▼
                       triple = fn(n) => n * 3

double(5) → 10
triple(5) → 15

Built-In Higher-Order Functions

JavaScript arrays come with several built-in higher-order functions. These are the most important ones to know.

map — Transform Every Item

map runs a function on each item and returns a new array with the results.

let temperatures = [0, 20, 37, 100]; // Celsius

let fahrenheit = temperatures.map(function(c) {
  return (c * 9/5) + 32;
});

console.log(fahrenheit); // [32, 68, 98.6, 212]

Diagram: map Flow

Input:  [0,  20,  37,  100]
         │    │    │     │
    fn → fn → fn → fn → fn  (apply conversion to each)
         │    │    │     │
Output: [32, 68, 98.6, 212]

filter — Keep Only What Passes

filter keeps items where the function returns true, and drops the rest.

let scores = [45, 72, 38, 90, 55, 80];

let passed = scores.filter(function(score) {
  return score >= 60;
});

console.log(passed); // [72, 90, 80]

reduce — Collapse Into One Value

reduce runs a function on each item and carries a running total (accumulator) through the array.

let cart = [200, 450, 150, 300];

let total = cart.reduce(function(accumulator, item) {
  return accumulator + item;
}, 0);

console.log(total); // 1100

Diagram: reduce Step by Step

Start: acc = 0
Step 1: acc = 0   + 200 = 200
Step 2: acc = 200 + 450 = 650
Step 3: acc = 650 + 150 = 800
Step 4: acc = 800 + 300 = 1100
Result: 1100

find — Get the First Match

let users = [
  { name: "Anjali", age: 22 },
  { name: "Rohan",  age: 30 },
  { name: "Meera",  age: 17 }
];

let adult = users.find(function(user) {
  return user.age >= 18;
});

console.log(adult.name); // "Anjali"

every and some

let ages = [22, 30, 25, 19];

console.log(ages.every(a => a >= 18)); // true  — all adults
console.log(ages.some(a => a >= 30));  // true  — at least one is 30+

Chaining Higher-Order Functions

You can chain these methods together to build a pipeline of transformations.

let products = [
  { name: "Shirt",  price: 500, inStock: true  },
  { name: "Shoes",  price: 2000, inStock: false },
  { name: "Cap",    price: 300,  inStock: true  },
  { name: "Jacket", price: 3000, inStock: true  }
];

let result = products
  .filter(p => p.inStock)         // only available items
  .map(p => p.price)              // extract prices
  .reduce((sum, p) => sum + p, 0); // total

console.log(result); // 3800  (500 + 300 + 3000)

Diagram: Chained Pipeline

products (4 items)
    │
    ▼ filter (inStock only)
  [Shirt, Cap, Jacket]  (3 items)
    │
    ▼ map (prices only)
  [500, 300, 3000]
    │
    ▼ reduce (sum)
  3800

Creating Your Own Higher-Order Function

function applyToAll(arr, transform) {
  let result = [];
  for (let item of arr) {
    result.push(transform(item));
  }
  return result;
}

let numbers = [1, 2, 3, 4];

let squared = applyToAll(numbers, n => n * n);
let doubled = applyToAll(numbers, n => n * 2);

console.log(squared); // [1, 4, 9, 16]
console.log(doubled); // [2, 4, 6, 8]

The same applyToAll function does different things depending on what transform function you give it.

Benefits of Higher-Order Functions

BenefitWhat It Means
ReusabilityWrite one function, use with many behaviors
ReadabilityCode describes what it does, not how step by step
ComposabilityChain small functions to build complex logic
Less codeNo need to write the same loop structure repeatedly

Summary

Higher-order functions treat other functions as values. They accept functions as arguments, return functions, or both. JavaScript's built-in array methods — map, filter, reduce, find, every, and some — are all higher-order functions. They make code shorter, cleaner, and easier to chain together into data pipelines.

Leave a Comment

Your email address will not be published. Required fields are marked *