Skip to content

Beginner · Functions and closures · topic 15 of 61 · 30 min

Higher-order functions and recursion

Explanation

A higher-order function takes a function as an argument or returns one; map, filter and setTimeout are examples. Writing your own shows how they work. Recursion is when a function calls itself on a smaller part of the problem, and it always needs a base case that stops it.

Higher-order functions

A higher-order function is a function that works with other functions: it takes one as an argument, returns one, or both. You already met makeCounter (returns a function) and sort (takes a compare function). They let you separate WHAT to do with each item from HOW to go through the items.

javascript
function repeat(times, action) {
  for (let i = 1; i <= times; i++) action(i);
}
repeat(3, (n) => console.log('Reminder', n));
Prints Reminder 1, Reminder 2, Reminder 3. repeat knows how to loop; the callback decides what happens.

Writing your own map and filter

Building simple versions yourself removes the mystery from the built-in array methods you will use daily (module 4).

javascript
function myMap(list, fn) {
  const out = [];
  for (const item of list) out.push(fn(item));
  return out;
}
function myFilter(list, test) {
  const out = [];
  for (const item of list) if (test(item)) out.push(item);
  return out;
}
console.log(myMap([1, 2, 3], (n) => n * 10));       // [10, 20, 30]
console.log(myFilter([5, 12, 8, 20], (n) => n > 9)); // [12, 20]

Recursion: a function that calls itself

Recursion solves a problem by solving a smaller copy of the same problem. Every recursive function has two parts: a base case, which answers the smallest problem directly and stops, and a recursive case, which calls the function again on a smaller input.

javascript
function factorial(n) {
  if (n <= 1) return 1;          // base case
  return n * factorial(n - 1);   // recursive case
}
console.log(factorial(5)); // 120 = 5 × 4 × 3 × 2 × 1

The call stack

The call stack is the list of function calls that are waiting to finish. Each call is stacked on top of the previous one, and each finishes in reverse order.

output
factorial(3)
  → 3 * factorial(2)
         → 2 * factorial(1)
                → 1          (base case)
         → 2 * 1 = 2
  → 3 * 2 = 6
How factorial(3) unwinds.
Careful: Without a correct base case, or with an input that never reaches it (factorial(-1) with if (n === 1)), the function calls itself forever until the engine stops it with RangeError: Maximum call stack size exceeded. Write the base case first, and make sure every call moves toward it.

Where recursion fits naturally

Recursion shines for nested data: folders inside folders, comments with replies, a menu with sub-menus, JSON inside JSON. A loop handles one level; recursion handles any depth.

javascript
function countFiles(folder) {
  let count = folder.files.length;
  for (const sub of folder.folders) count += countFiles(sub);
  return count;
}
const drive = { files: ['a.pdf'], folders: [
  { files: ['b.jpg', 'c.jpg'], folders: [] },
  { files: [], folders: [{ files: ['d.txt'], folders: [] }] },
] };
console.log(countFiles(drive)); // 4
Think of it like this: Recursion is like a set of Russian dolls, or opening a box of sweets that contains smaller boxes. You open the outer box, and for each small box inside you do exactly the same thing, until you reach a box with only sweets in it (the base case).
Tip: For very deep inputs (hundreds of thousands of levels), a loop is safer than recursion because the call stack is limited. Use recursion when it makes the code much clearer and the depth is reasonable.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Higher-order functions and recursion · 1/7

Higher-order functions and recursion

In this lesson you will write higher-order functions and recursive functions.

Prefer a video by a teacher? Find free videos on “javascript higher order functions recursion call stack” on YouTube ↗

In real life: Total price of a nested category tree

An e-commerce admin panel stores categories inside categories (Electronics → Phones → Accessories). To show the value of stock in a category, the code adds the products in it plus, recursively, every sub-category.

javascript
function stockValue(cat) {
  let sum = cat.products.reduce((s, p) => s + p.price * p.qty, 0);
  for (const sub of cat.children) sum += stockValue(sub);
  return sum;
}
const phones = { products: [{ price: 15000, qty: 2 }], children: [] };
const electronics = { products: [{ price: 40000, qty: 1 }], children: [phones] };
console.log(stockValue(electronics)); // 70000

Practice (0/3 done)

Task 1 · Code · Javascript

Write myFilter(list, test) that returns a new array with only the items for which test(item) is true. Do not use the built-in filter.

Task 2 · Code · Javascript

Write a recursive function power(base, exp) for whole numbers exp >= 0, without using ** or Math.pow. power(2, 10) is 1024.

Task 3 · Code · Javascript

Write sumNested(arr) that adds every number in an array that may contain arrays inside arrays, to any depth. sumNested([1, [2, [3, 4]], 5]) is 15.

Quick quiz

Question 1

1.Which is a higher-order function?

Question 2

2.What does every recursive function need to stop?

Question 3

3.function f(n) { return n === 0 ? 0 : n + f(n - 1); } What is f(4)?

Question 4

4.What error does endless recursion cause?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which is a higher-order function?

Answer: A function that takes another function as an argument

Higher-order functions take or return functions.

What does every recursive function need to stop?

Answer: A base case

The base case answers the smallest input directly without calling itself.

function f(n) { return n === 0 ? 0 : n + f(n - 1); } What is f(4)?

Answer: 10

4 + 3 + 2 + 1 + 0 = 10.

What error does endless recursion cause?

Answer: RangeError: Maximum call stack size exceeded

Each call uses stack space until the engine refuses with a RangeError.

What happens if a recursive function has no reachable base case?Related

Answer: It keeps calling itself until Python raises RecursionError

Every call adds a frame; with no base case the stack grows until the recursion limit (about 1,000 in Python) is hit.

From Recursion: functions that call themselves

What are the two parts every recursive function needs?Related

Answer: A base case and a recursive case that gets closer to it

Without a base case it never stops; without progress it never reaches the base case.

From Overloading, default arguments and recursion

What happens if a recursive function has no base case?Related

Answer: Python raises RecursionError after about 1000 nested calls

The calls keep stacking up until Python's recursion limit stops them with RecursionError.

From Recursion and sorting algorithms

What usually happens when recursion goes too deep in C?Related

Answer: A stack overflow, typically a segmentation fault

The call stack runs out of space.

From Recursion

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Functions and closures”. The module exam comes next.
  2. Module 3 exam: Functions and closures · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Arrays and objects. 61 topics left in the course before the final exam.

← Previous: Scope and closures