JavaScript递归中的递减操作:两个阶乘函数为何输出不同?
两段阶乘递归代码的差异及输出异常原因
先看两段代码的具体实现:
// 第一段代码(正确计算阶乘) const factorial = (n) => { if (n === 0) return 1; return factorial(n - 1) * n; }; console.log(factorial(5)); //Output: 120 // 第二段代码(输出异常) const factorial = (n) => { if (n === 0) return 1; return factorial(--n) * n; }; console.log(factorial(5)); //Output: 0
核心区别
两段代码的核心差异在于递归调用时对参数n的处理方式:
- 第一段用
n - 1传递参数:这是单纯的数值计算,只会把n减1后的结果传给下一次递归,当前函数作用域内的n值不会发生变化。 - 第二段用
--n传递参数:--是前置自减运算符,会先把当前作用域内的n值直接减1,再将减后的值传给递归调用,当前n的值被永久修改。
第二段代码输出0的原因
我们一步步拆解factorial(5)的执行流程就能明白:
- 调用
factorial(5):n≠0,执行factorial(--5) * 5——先把n改成4,再调用factorial(4),后续乘法用的是已经变成4的n。 - 调用
factorial(4):n≠0,执行factorial(--4) * 4——n改成3,调用factorial(3),乘法用3。 - 调用
factorial(3):n≠0,执行factorial(--3) * 3——n改成2,调用factorial(2),乘法用2。 - 调用
factorial(2):n≠0,执行factorial(--2) * 2——n改成1,调用factorial(1),乘法用1。 - 调用
factorial(1):n≠0,执行factorial(--1) * 1——关键步骤:先把n改成0,调用factorial(0)返回1,然后乘法用的是已经变成0的n,所以这一步的结果是1 * 0 = 0。 - 递归回溯:后续所有上层调用都会用这个0去乘当前的n值,最终结果自然是0。
简单来说,就是--n修改了当前作用域的n值,导致最底层递归返回后,乘的是已经被改成0的n,直接让整个计算链的结果变成0。
内容的提问来源于stack exchange,提问作者Evgeniy
相关产品推荐
相关产品推荐

