JavaScript递归案例foo(3)执行逻辑与运行结果疑问解答
JavaScript递归代码运行逻辑解答
首先给出完整代码:
let ar = []; function foo(i) { if (i < 0) return console.log("test"); ar.push(i); console.log(i, Boolean(i<0)); foo(i - 1); ar.push(i); console.log(i, Boolean(i<0)); } foo(3) console.log('ar=', JSON.stringify( ar ))
运行后的控制台输出如下:
3 false 2 false 1 false 0 false test 0 false 1 false 2 false 3 false ar= [3,2,1,0,0,1,2,3
调用foo(3)时表达式0 < 0的求值逻辑
当递归调用到foo(0)时,if判断条件i < 0即0 < 0会被执行:JavaScript中数字0属于number类型,0和0做小于比较,运算结果为布尔值false,因此if分支的return逻辑被跳过,函数继续执行后续的ar.push(0)、console.log等代码。
return语句后直接返回console.log("test")是否属于特殊用法
不属于特殊用法,是JavaScript常规的表达式求值逻辑:
console.log("test")执行后会输出对应内容,本身的返回值固定为undefined- 该写法等价于先执行
console.log("test"),再将其返回值undefined作为foo函数的返回值返回,拆分成两行写效果完全一致:console.log("test"); return;
ar数组索引3和4位置的两个0是否是0值被求值两次
不是,两个0是同一个foo(0)函数执行上下文的ar.push(i)分别在递推、回溯阶段各执行一次导致的:
- 第一个0(索引3)是递推阶段生成:刚进入
foo(0)时第一次执行ar.push(0),此时ar为[3,2,1,0] - 第二个0(索引4)是回溯阶段生成:
foo(-1)执行完毕返回后,回到foo(0)中递归调用foo(i-1)后的代码继续执行,第二次执行ar.push(0),此时ar为[3,2,1,0,0]
1-1计算时是否会触发foo(0)调用
是的,foo(1)执行到递归调用语句foo(i - 1)时,i的值为1,i-1计算结果为0,会直接触发foo(0)调用。
递归调用位于两次push和log之间对执行顺序的影响
这个代码顺序直接决定了两段操作分别在递归的不同阶段执行:
- 递归调用前的
ar.push(i)和console.log属于递推阶段执行:调用链从外层到内层逐层执行,i按3→2→1→0的顺序执行,对应第一次打印顺序为3、2、1、0 - 递归调用后的
ar.push(i)和console.log属于回溯阶段执行:调用链从内层返回外层时逐层执行,i按0→1→2→3的顺序执行,对应第二次打印顺序为0、1、2、3
最终ar数组的内容也由这个顺序决定,呈现先递推入栈3、2、1、0,再回溯入栈0、1、2、3的规律,得到最终的数组结果。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

