递归函数是函数调用自身,必须有明确终止条件(base case),否则导致栈溢出;核心结构为base case加recursive case,常见错误包括缺return、base case条件错误、问题规模未缩小。
递归函数就是函数自己调用自己。在 JavaScript 中能用,但必须有明确的终止条件,否则会无限调用导致 RangeError: Maximum call stack size exceeded。
写递归函数时,先想清楚两件事:什么时候停止?(base case);其余情况怎么缩小问题规模并交给自己处理?(recursive case)
却用了 )→ 可能跳过终止,同样栈溢出
例如计算阶乘:
function factorial(n) {
if (n < 0) return NaN; //
非法输入防护
if (n === 0 || n === 1) return 1; // base case
return n * factorial(n - 1); // recursive case:规模减 1
}JavaScript 中如果函数体末尾没写 return,默认返回 undefined。递归里漏掉 return,会导致上层拿到 undefined,后续计算崩掉。
立即学习“Java免费学习笔记(深入)”;
factorial(3) 中 return n * factorial(n - 1) 写成 n * factorial(n - 1)(无 return)→ 返回 undefined
return 出去console.log('factorial called with', n),看是否卡住或重复进入JavaScript 引擎不普遍支持尾调用优化(TCO),所以深度递归容易爆栈。简单循环能解决的问题,优先用 for 或 while。
fib(n) = fib(n-1) + fib(n-2))时间复杂度是 O(2^n),实际项目中要避免Array 模拟),或设最大深度保护(如加参数 depth 并在 base case 中检查)递归不是炫技,是为匹配问题本身的结构。写之前先画两层调用链,确认 base case 能被触达,再动手。否则修 bug 的时间远超写代码的时间。