JavaScript递归参数状态疑问:阶乘函数fac参数运行逻辑求解
递归阶乘函数的参数状态维护逻辑
你之前理解的计算流程其实是迭代实现阶乘的逻辑,和递归的执行逻辑完全不同。这个递归函数里fac参数的状态是靠JS的**调用栈(Call Stack)**维护的:每触发一次factorial调用,引擎都会在调用栈中创建一个独立的函数执行上下文,每个上下文里的fac参数都是独立存储的,不同层的调用不会互相干扰。
factorial(4)的完整执行步骤拆解:
- 首次调用
factorial(4),第一层执行上下文入栈,当前fac = 4,不满足fac == 1的终止条件,需要等待factorial(3)的返回结果,当前上下文暂时挂起 - 调用
factorial(3),第二层执行上下文入栈,当前fac = 3,不满足终止条件,等待factorial(2)的返回结果,上下文挂起 - 调用
factorial(2),第三层执行上下文入栈,当前fac = 2,不满足终止条件,等待factorial(1)的返回结果,上下文挂起 - 调用
factorial(1),第四层执行上下文入栈,当前fac = 1,满足终止条件,直接返回1,第四层上下文出栈销毁 - 回溯到第三层上下文,取出之前存储的
fac = 2,计算2 * 1 = 2并返回,第三层上下文出栈销毁 - 回溯到第二层上下文,取出之前存储的
fac = 3,计算3 * 2 = 6并返回,第二层上下文出栈销毁 - 回溯到第一层上下文,取出之前存储的
fac = 4,计算4 * 6 = 24并返回,第一层上下文出栈销毁,得到最终计算结果
你在debugger的调用栈面板可以看到每一层挂起的上下文,点开就能看到对应层存储的fac值,都是独立保存的。
认知偏差说明
你之前以为的计算顺序是4*3=12 → 12*2=24 → 24*1=24,是从左到右的正向计算;但递归的实际计算顺序是从最内层的终止条件开始反向计算,也就是1*2*3*4,每一层的fac在调用入栈的时候就已经存好了,回溯计算的时候直接读取即可,不会被其他层的调用修改。
内容的提问来源于stack exchange,提问作者Ittisafur
相关产品推荐
相关产品推荐

