Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Higher-Order Functions and Recursion in JavaScript

Higher-Order Functions and Recursion in JavaScript

~13 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

Two advanced, closely related function concepts: functions that take other functions as parameters or return them ("higher-order functions", which we already use daily via map/filter/reduce from chapter 11), and functions that call THEMSELVES (recursion).

What is a higher-order function?

A function is "higher-order" if it has at least ONE of two properties: it takes a function as an argument, OR it returns a function.

// Takes a function as an argument:
function processTransactions(transactions, processFn) {
  return transactions.map(processFn);
}

const amounts = processTransactions(
  [{ amount: 2400 }, { amount: -850 }],
  t => t.amount
);
console.log(amounts); // [2400, -850]

Functions that return functions

A powerful pattern: a function FACTORY that creates a specialized function based on a parameter – for our budget app, e.g. a factory for category filters:

function createCategoryFilter(category) {
  return function (transaction) {
    return transaction.category === category;
  };
}

const transactions = [
  { description: 'Rent', category: 'Housing', amount: -850 },
  { description: 'Electricity', category: 'Housing', amount: -60 },
  { description: 'Movies', category: 'Leisure', amount: -18 },
];

const isHousing = createCategoryFilter('Housing'); // EXACTLY like chapter 16: a closure!
const housingCosts = transactions.filter(isHousing);

console.log(housingCosts); // Rent and Electricity

Tipp: This is the same closure mechanism from chapter 16 – higher-order functions and closures often go hand in hand in practice: the returned function "remembers" the outer function's category parameter.

Function composition: combining small functions

const onlyExpenses = transactions => transactions.filter(t => t.amount < 0);
const sumAmounts = transactions => transactions.reduce((s, t) => s + t.amount, 0);

function calculateTotalExpenses(transactions) {
  return sumAmounts(onlyExpenses(transactions));
}

console.log(calculateTotalExpenses(transactions)); // -928

Recursion: a function calling itself

A recursive function always needs two parts: a base case ("when does the recursion stop?"), and a recursive case that shrinks the problem and calls itself again:

function factorial(n) {
  if (n <= 1) {
    return 1; // base case
  }
  return n * factorial(n - 1); // recursive case - a smaller problem
}

console.log(factorial(5)); // 120 (5 * 4 * 3 * 2 * 1)

Achtung: If the base case is missing or never reached, it causes infinite recursion and a "Maximum call stack size exceeded" error once the call stack (chapter 23) fills up.

Practical example: nested category tree totals

Recursion is especially suited to tree structures – e.g. if categories are allowed to have subcategories:

src/index.js
const categoryTree = {
  name: 'All expenses',
  amount: 0,
  subcategories: [
    { name: 'Housing', amount: -910, subcategories: [] },
    {
      name: 'Leisure', amount: 0,
      subcategories: [
        { name: 'Movies', amount: -18, subcategories: [] },
        { name: 'Sports', amount: -35, subcategories: [] },
      ],
    },
  ],
};

function sumTree(node) {
  let total = node.amount;
  for (const subcategory of node.subcategories) {
    total += sumTree(subcategory); // recursive call per level
  }
  return total;
}

console.log(sumTree(categoryTree)); // -963