为何JavaScript传入n=1调用递归函数仍触发栈溢出错误
递归斐波那契函数调用栈溢出原因
核心问题原因
你写的递归函数把终止条件判断放在了递归调用语句之后,导致无论传入什么参数,函数进入后都会先无限制触发递归,永远执行不到终止判断的逻辑,最终撑爆调用栈。
执行流程拆解(以传入n=1为例)
- 调用
f(1),进入函数体后不会先判断n的值,直接执行第一行代码const f1 = f(n - 1),发起f(0)的调用 - 进入
f(0)的执行上下文,同样不做判断直接执行第一行const f1 = f(0-1),发起f(-1)的调用 - 进入
f(-1)的执行上下文,继续直接调用f(-2),n会持续往负方向无限递减,每一次调用都会往JS调用栈压入新的执行帧 - 整个过程永远不会走到后面写的
n == 0 ? 0 : (n == 1 ? 1 : f1 + f2)返回逻辑,直到调用栈长度超出JS引擎的上限,就会抛出栈溢出错误。
修复方案
把递归终止条件的判断移动到函数最开头,进入函数先校验是否满足终止要求,命中就直接返回结果,不触发后续递归调用:
function f(n) { // 终止条件前置,先判断再执行递归 if (n === 0) return 0; if (n === 1) return 1; const f1 = f(n - 1); const f2 = f(n - 2); return f1 + f2; } console.log(f(1)); // 正常输出结果1
如果要保留原有的三目运算符写法,只要保证递归调用逻辑在终止判断之后执行即可,不需要强制改成if结构。
额外说明:即使修复了判断顺序,这种朴素递归写法计算大n值的斐波那契数时会存在大量重复计算,性能很差,实际使用可以搭配记忆化缓存,或者直接改用迭代写法。
内容的提问来源于stack exchange,提问作者user310291
相关产品推荐
相关产品推荐

