DEV Community

Cover image for Recursion
Monicah Ajeso
Monicah Ajeso

Posted on

Recursion

"A function that calls itself sounds like a bug. Turns out it's one of the most powerful ideas in programming."

When you first hear "a function that calls itself" — your brain says wait, wouldn't that just loop forever? Good instinct. That's exactly the right question to ask. And the answer is what makes recursion beautiful.

What is Recursion?

Recursion is when a function calls itself to solve a smaller version of the same problem — until it hits a point where it doesn't need to anymore.

Every recursive function has two parts:

  • Base case — the condition that stops the recursion. Without this, you get infinite calls and a crashed browser.
  • Recursive case — where the function calls itself with a smaller input, working towards the base case.

💡 Think of it like: Russian nesting dolls. You keep opening a doll to find a smaller one inside — until you reach the tiniest one that doesn't open. That's your base case.


The Call Stack — A Quick Mention

When a function calls itself, JavaScript doesn't forget what it was doing. Each call gets stacked on top of the previous one — waiting for the one above it to finish first.

countdown(3)
  countdown(2)
    countdown(1)
      countdown(0) ← base case hit, start returning
    ↩ back to countdown(1)
  ↩ back to countdown(2)
↩ back to countdown(3)
Enter fullscreen mode Exit fullscreen mode

This stack of waiting calls is called the call stack. Once the base case is reached, the stack unwinds — each call finishes and returns, one by one.


Example 1 — Countdown

Let's start simple. Count down from any number to zero.

Without recursion:

function countdown(n) {
  for (let i = n; i >= 0; i--) {
    console.log(i);
  }
}

countdown(3); // 3, 2, 1, 0
Enter fullscreen mode Exit fullscreen mode

With recursion:

function countdown(n) {
  if (n < 0) return; // base case — stop here

  console.log(n);
  countdown(n - 1); // recursive case — call with a smaller number
}

countdown(3); // 3, 2, 1, 0
Enter fullscreen mode Exit fullscreen mode

Here's what happens step by step:

countdown(3) → prints 3, calls countdown(2)
countdown(2) → prints 2, calls countdown(1)
countdown(1) → prints 1, calls countdown(0)
countdown(0) → prints 0, calls countdown(-1)
countdown(-1) → n < 0, returns. Done.
Enter fullscreen mode Exit fullscreen mode

💡 The base case here is n < 0 — once we go below zero, stop. Without it, this runs forever.


Example 2 — Factorial

The factorial of a number is that number multiplied by every positive integer below it.

5! = 5 × 4 × 3 × 2 × 1 = 120
4! = 4 × 3 × 2 × 1 = 24
1! = 1
0! = 1 (by definition)
Enter fullscreen mode Exit fullscreen mode

Factorial is a perfect recursion problem because each step is just: "this number times the factorial of the number below it."

Without recursion:

function factorial(n) {
  let result = 1;
  for (let i = n; i > 1; i--) {
    result *= i;
  }
  return result;
}

factorial(5); // 120
Enter fullscreen mode Exit fullscreen mode

With recursion:

function factorial(n) {
  if (n <= 1) return 1; // base case

  return n * factorial(n - 1); // recursive case
}

factorial(5); // 120
Enter fullscreen mode Exit fullscreen mode

Here's what that looks like unwinding:

factorial(5)
= 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 * factorial(1)
= 5 * 4 * 3 * 2 * 1
= 120
Enter fullscreen mode Exit fullscreen mode

💡 The base case is n <= 1 — because 1! = 1 and 0! = 1. Once we hit it, the stack starts returning values back up the chain.


Recursion vs Iteration — Which Should You Use?

Both can solve the same problems. Here's how to think about it:

Recursion Iteration (loops)
Readability Clean for complex problems Clean for simple problems
Performance Can be slower (call stack overhead) Usually faster
Best for Trees, nested structures, divide & conquer Counting, simple repetition

💡 If you can solve it easily with a loop — use a loop. Reach for recursion when the problem naturally breaks into smaller versions of itself.


The Two Rules of Recursion

Before you write any recursive function, ask yourself:

  1. What is my base case? — When do I stop?
  2. Am I moving towards it? — Is each recursive call working towards the base case?

If you can't answer both questions, you're not ready to write the function yet.


Recursion isn't magic — it's just a function with a very good memory and a clear exit plan.

And now you know when to use it.

Happy coding!!! 😊

Top comments (0)