最近我一直在努力理解递归以及一切实际如何工作,所以我写了这个js函数
function checkScope(times){
if(times == 1){
console.log(`Times is ${times}`);
}else{
checkScope(times-1);
console.log(`Times is ${times}`)
}
}
根据我的理解,我相信如果我用以下方式调用此函数:
checkScope(3)
首先执行else块中的第一个语句,然后再次调用该函数,然后发生同样的事情,这次变量times = 1,所以我应该得到“Times is 1”的日志。也许当控制权转移回调用函数时,最后一行代码执行:
Times is [I dont know what times should be at this time :(]
但是当我运行时,我最终得到了
Times is 1
Times is 2
Times is 3
作为我的输出,请我解释一下。
答案 0 :(得分:2)
它与console.log()
和checkScope()
函数调用的顺序相关。由于您首先调用checkScope()
函数,因此最终控制台将记录最后一项。
所以你应该按如下方式替换行的顺序:
function checkScope(times){
if(times == 1){
console.log(`Times is ${times}`);
}else{
console.log(`Times is ${times}`)
checkScope(times-1);
}
}
checkScope(3);

为了更好地理解,请检查一下。
function checkScope(times){
console.log("checkScope("+times+") called.");
if(times == 1){
console.log(`Times is ${times}`);
}else{
console.log(`Times is ${times}`)
checkScope(times-1);
}
console.log("checkScope("+times+") returned.");
}
checkScope(3);

答案 1 :(得分:2)
也许当控制权转移回调用函数时......
...然后你需要记住那是什么。在这种情况下,第三个调用(记录1
)确实返回到第二个调用,该调用继续在那里的console.log
语句。那里times
没有什么价值?要理解的主要问题是每个调用都维护其局部变量 - 在第二个调用中,times
为2
。然后在记录之后它从第二次调用返回到第一次调用。在那里,times
的值为3
,会被记录。然后它最终从第一次调用返回到调用站点checkScope(3)
,然后脚本结束。
答案 2 :(得分:1)
很简单。请参阅,在第4行console.log
调用后调用checkScope
。这会导致所有console.log
调用被推迟到递归解析的时间(times == 1
)。所以这里会发生什么:
Times is ${times}
); //第二行有1个Times is ${times}
)//在第5行有2个Times is ${times}
)//在第5行有3个答案 3 :(得分:1)
您始终可以使用调试器查看流程,无论如何请查看以下说明
checkScope(3)
since times = 3
checkScope(2) is called
since times = 2
checkScope(1) is called
logs: Times is 1
returns
logs: Times is 2
returns
logs: Times is 3
returns
我希望这可以帮助您理解代码
答案 4 :(得分:1)
所以让我们一步一步来,你打电话给checkScope(3)
一般来说,你应该记住的是有一个叫做“调用堆栈”的东西。您可以将其视为一个堆栈,其中所有函数都被称为go。顶部的功能是当前执行的功能。函数完成后,它会从堆栈中退出,然后下一个函数位于顶部。
在checkScope(3)中,当调用checkScope的新实例时,它将被置于checkScope(3)上。因此,在调用checkScope(2)的步骤4中,调用堆栈将是:
在第7步,调用堆栈将是:
在步骤8,调用堆栈是:
在步骤10,调用堆栈:
当我们到达第11步时,调用堆栈为空,因为所有调用的函数现已终止。
答案 5 :(得分:1)
这使它更清楚
因此,由于在= = 1之前的前一个函数调用都没有到达它们的最后一行,在次= = 1之后,所有其他函数执行它们的最后几行代码,这些代码就是console.log()行时变量值。