Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Recursion

Recursion is a technique in which a function calls itself. A big task is reduced to the same task but slightly smaller, and so on until it becomes trivial. Recursion is handy for walking nested structures: folders with subfolders, comments with replies, menus with submenus.

A function calls itself

A recursive function calls itself in its body with a different argument. Here is a countdown:

function countdown(n) {
  if (n === 0) {
    return;
  }
  console.log(n);
  countdown(n - 1);
}
 
countdown(3);
// 3
// 2
// 1

Each call prints a number and passes a number one smaller to the next call.

The base case

The condition under which the function stops calling itself is called the base case. In the example above it is n === 0: on reaching zero, the function simply ends. Without a base case the recursion would never finish. That is why you start writing a recursive function with it: first solve the simplest version of the task, then reduce the rest to it.

Returning a result

A recursive function can return a value. The sum of the numbers from 1 to n can be described like this: it is n plus the sum of the numbers from 1 to n - 1:

function sumTo(n) {
  if (n === 1) {
    return 1;
  }
  return n + sumTo(n - 1);
}
 
console.log(sumTo(4)); // 10

The call sumTo(4) becomes 4 + sumTo(3), then 4 + 3 + sumTo(2) and finally 4 + 3 + 2 + 1.

Factorial

The classic example of recursion is the factorial: the product of all numbers from 1 to n. The factorial of 5 is 5 * 4 * 3 * 2 * 1:

function factorial(n) {
  if (n <= 1) {
    return 1;
  }
  return n * factorial(n - 1);
}
 
console.log(factorial(5)); // 120

The call stack

While a nested call is working, the outer one waits for its result. JavaScript keeps the waiting calls in the call stack — a list where new calls are placed on top and removed when they finish. The stack has a limited size — usually a few thousand calls — so very deep recursion will not work.

Recursion or a loop

Any recursion can be replaced with a loop and vice versa. For simple counting a loop is clearer and does not use up the stack:

let result = 1;
 
for (let i = 2; i <= 5; i++) {
  result *= i;
}
 
console.log(result); // 120

Recursion is chosen when the data itself is recursive — like a folder tree or nested comments.

Common mistake

If you forget the base case, or the argument does not move towards it, the function calls itself forever. The stack overflows, and the program stops with an error:

function countdown(n) {
  countdown(n - 1); // no exit condition
}
 
countdown(3); // RangeError: Maximum call stack size exceeded

Before running a recursive function, check two things: is there a base case, and does the argument get closer to it with every call?

Thanks for reading!

Donate to the site — we work hard for you.