Recursion
In short: a recursive function solves a problem by calling itself
on a smaller version of it, over and over, until it hits a base case —
a version so small it needs no further call, and just returns a plain
value. Every call waits, on the call stack, for the call it made to come
back with an answer; once the base case returns, the answers combine as
the calls unwind back out, one level at a time. No base case, or one
that's never actually reached, means the calls never stop — a RangeError
waiting to happen.
![Nested Russian dolls, sumArray([10,20,30,40]) opening sumArray([20,30,40]) opening sumArray([30,40]) opening sumArray([40]), down to the smallest doll — the base case, sumArray([]) → 0 — then the dolls close back up, unwinding 0 → 40 → 70 → 90 → 100](/api/assets/javascript/assets/199ccba722a8cda1.png)
Summing an array one item at a time
The classic shape: handle one piece, then hand the rest to a smaller call of the same function.
sumArray([10, 20, 30, 40]) calls sumArray([20, 30, 40]), which calls
sumArray([30, 40]), and so on, until sumArray([]) hits the base case
and returns 0 without calling anything further. Then each waiting call
adds its own first item to what came back: 0 → 40 → 70 → 90 → 100.
Adding up a nested folder tree
Recursion earns its keep on data that's nested arbitrarily deep — a regular loop can't walk this shape naturally:
A file is the base case — it just returns its own size. A folder isn't:
it calls folderSize again on every child, however deeply nested, and
sums whatever comes back. The function doesn't need to know the tree's
depth in advance; the recursion handles however deep it happens to go.
The trap: a base case that's never reached
Removing the base case doesn't make the function skip straight to the answer — it just never stops:
With no if (nums.length === 0) return 0;, sumArrayBroken keeps calling
itself on shorter and shorter — eventually empty — arrays forever, since
[].slice(1) is still []. Every call pushes another frame that can
never pop, until the call stack hits its limit and throws
RangeError: Maximum call stack size exceeded — the same error a
never-ending call chain always produces.
Quick practice
In a correct recursive function, what is the base case for?
For sumArray([5, 10]) using the base-case version above, what is the order of returns as the calls unwind?
What does sumArrayBroken from the last example throw, and why?
