Deep recursion
With deep recursion (that is, when a function calls itself many times before reaching the base case), JavaScript can produce a call stack overflow - a RangeError: Maximum call stack size exceeded error.
What happens "under the hood"
Every time a function calls itself, JS creates a new execution context (a stack frame) on the call stack:
factorial(5)
→ factorial(4)
→ factorial(3)
→ factorial(2)
→ factorial(1)Each call stores:
- local variables,
- arguments,
- the return address.
When the base case is reached, the stack "unwinds" back. But if there are too many calls, the stack overflows.
Example of a stack overflow
function recurse(n) {
console.log(n);
recurse(n + 1); // no base case!
}
recurse(1);Error:
RangeError: Maximum call stack size exceededThe browser (or Node.js) allocates a limited stack size, usually around 10,000-20,000 nested calls.
Even with a base case, you can hit the limit
function countdown(n) {
if (n === 0) return;
countdown(n - 1);
}
countdown(100000); // RangeErrorDespite having a base case, the recursion depth (100,000) is too large for the JS stack.
How to avoid the problem
1. Rewrite the recursion as a loop
function countdown(n) {
while (n > 0) n--;
}2. Use tail recursion (if it were optimized)
function countdown(n) {
if (n === 0) return;
return countdown(n - 1); // tail call
}But: most JS engines do not implement tail call optimization.
3. Split the recursion into "chunks" via setTimeout
function countdown(n) {
if (n === 0) return;
console.log(n);
setTimeout(() => countdown(n - 1), 0); // does not block the stack
}Here each call runs on a new event loop iteration, so the stack does not grow.
Summary
| Phenomenon | What happens |
|---|---|
| Deep recursion | Many nested calls of the same function |
| Result | Stack overflow (RangeError) |
| Why | Each call creates a new context on the stack |
| How to avoid it | Use a loop, tail recursion, or setTimeout |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.