Beginner · Functions and closures · topic 15 of 61 · 30 min
Higher-order functions and recursion
Explanation
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.
function repeat(times, action) {
for (let i = 1; i <= times; i++) action(i);
}
repeat(3, (n) => console.log('Reminder', n));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).
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.
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 × 1The 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.
factorial(3)
→ 3 * factorial(2)
→ 2 * factorial(1)
→ 1 (base case)
→ 2 * 1 = 2
→ 3 * 2 = 6Where 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.
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)); // 4Need 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
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.
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)); // 70000Practice (0/3 done)
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.
Write a recursive function power(base, exp) for whole numbers exp >= 0, without using ** or Math.pow. power(2, 10) is 1024.
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
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Parameters: defaults, rest and options objectsFunctions and closures · same module
- Recursion: functions that call themselvesData Structures and Algorithms (DSA) for interviews · Recursion and backtracking
- Overloading, default arguments and recursionC++ Programming (modern C++ and DSA) · Decisions, loops and functions
- Recursion and sorting algorithmsPython Programming · Algorithms, data structures and testing
- RecursionC Programming (from zero to systems) · Functions and arrays
- Best, average and worst case; analysing loops and recursionData Structures and Algorithms (DSA) for interviews · Thinking in Big-O
Questions people ask about this
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.
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.
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.
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
- This is the last topic of “Functions and closures”. The module exam comes next.
- Module 3 exam: Functions and closures · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Arrays and objects. 61 topics left in the course before the final exam.