JavaScript递归调试解惑:阶乘函数多余1输出疑问
递归阶乘代码的执行流程解析
首先先看你提供的这段递归代码:
function fact(n){ if(n ==1){ return 1 } else{ console.log(fact(n-1)) return n*fact(n-1) } }
你困惑的点在于,为什么除了最底层if(n==1)返回的那个1,控制台还会打印出其他的1?其实核心原因很简单——这段代码在else分支里重复调用了两次fact(n-1),这两次调用是完全独立的,都会触发完整的递归流程,导致底层的fact(1)被多次执行,每次执行都会返回1,当上层的console.log捕获到这个返回值时,就会打印出来。
让我们用具体的调用例子一步步拆解:
例子1:调用fact(2)的完整流程
- 调用
fact(2),n不等于1,进入else分支 - 首先执行
console.log(fact(1)):- 触发
fact(1)的调用,n=1满足条件,直接返回1 - 控制台打印第一个
1
- 触发
- 接着执行
return 2 * fact(1):- 又一次触发
fact(1)的调用,再次返回1 - 计算得到
2*1=2,作为fact(2)的返回值
- 又一次触发
例子2:调用fact(3)的完整流程
- 调用
fact(3),n不等于1,进入else分支 - 先执行
console.log(fact(2)):- 进入
fact(2)的执行流程:- 先调用
fact(1),控制台打印第一个1 - 再调用
fact(1),返回2
- 先调用
- 控制台接着打印
2
- 进入
- 然后执行
return 3 * fact(2):- 再次进入
fact(2)的执行流程:- 又一次调用
fact(1),控制台打印第二个1 - 再调用
fact(1),返回2
- 又一次调用
- 计算得到
3*2=6,作为fact(3)的返回值
- 再次进入
所以调用fact(3)时,你会在控制台看到先打印1,再打印2,最后又打印一个1——这就是那些额外1的来源。
如果要解决这个冗余调用的问题,你可以把递归的结果存到一个变量里复用,避免重复触发递归:
function fact(n){ if(n ==1){ return 1 } else{ const prevFact = fact(n-1) console.log(prevFact) return n*prevFact } }
这样每次递归只会调用一次fact(n-1),打印的内容也会更符合预期,比如调用fact(3)会依次打印1、2,最终返回6。
内容的提问来源于stack exchange,提问作者siddharth shah
相关产品推荐
相关产品推荐

