How does recursion work in JavaScript, and what makes a recursive function correct?
A recursive function is one that calls itself with a smaller version of the same problem. It is correct when two things are true: there is a base case that returns a result without recursing, and the recursive call moves towards that base case.
function sum(numbers) {
if (numbers.length === 0) {
return 0; // base case
}
return numbers[0] + sum(numbers.slice(1)); // smaller problem
}
console.log(sum([1, 2, 3, 4])); // 10Every call gets its own stack frame holding its parameters and its local variables, and the frames pile up until a call returns, at which point the frame is popped and control goes back to the caller. That is why the sum above reads naturally: each call adds its own first element to whatever the rest of the array adds up to.
The two failure modes to know about are a missing or unreachable base case, which produces infinite recursion, and a recursive call that does not shrink the problem, which produces the same thing more slowly. Both end in a RangeError when the stack runs out.
There is also a cost consideration. Each call allocates a stack frame, so recursion uses more memory than a loop, and the engine has to copy arguments into every frame. For anything that processes a large collection, a loop is usually the better choice. Recursion earns its place when the problem is naturally recursive, such as traversing a tree structure, where the shape of the code matches the shape of the data and the alternative requires an explicit stack.