简体   繁体   English

这个递归函数如何解析以及为什么它输出它所做的

[英]How does this recursive function resolve and why does it output what it does

I found myself unable to understand this example of a recursive function:我发现自己无法理解这个递归函数的例子:

function foo(i) {
  if (i < 0)
    return;
  console.log('begin:' + i);
  foo(i - 1);
  console.log('end:' + i);
}
foo(3);

The output is:输出是:

begin:3
begin:2
begin:1
begin:0
end:0
end:1
end:2
end:3

I understand how normal and nested functions work, and I think the return;我了解普通函数和嵌套函数的工作原理,我认为return; here is supposed to exit the function when i gets lower than 0 , so when i = -1 , the first console.log() didn't show, but why after foo(-1 - 1) we get the output end:0 ?这里应该在i低于0时退出函数,所以当i = -1 ,第一个console.log()没有显示,但是为什么在foo(-1 - 1)我们得到输出end:0 ?

To understand you must visualize the stack. 要了解您必须可视化堆栈。 Let me take you through the execution process: 让我带您完成执行过程:

  1. We start by calling foo(3) , so i is 3. Since i is not less than 0, log begin:3 . 我们从调用foo(3) ,所以i是3.因为i不小于0,所以log begin:3 Call foo(2) 打电话给foo(2)
  2. i is now 2. Since i is not less than 0, log begin:2 . i现在是2.因为i不小于0,所以记录begin:2 Call foo(1) foo(1)
  3. i is now 1. Since i is not less than 0, log begin:1 . i现在是1.因为i不小于0,所以记录begin:1 Call foo(0) foo(0)
  4. i is now 0. Since i is not less than 0, log begin:0 . i现在是0.因为i不小于0,所以log begin:0 Call foo(-1) 调用foo(-1)
  5. i is now -1. i现在是-1。 Since i is less than 0, we return and go up the stack. 由于i 小于0,我们返回去堆栈。 Continue from where we left off, the second log in foo(0) : 从我们离开的地方继续,第二次登录foo(0)

     console.log('end:' + i); 

    end:0 is logged because i is equal to 0. foo(0) has resolved, go up the stack to foo(1) end:0被记录,因为i等于0. foo(0)已经解决,向上移动堆栈到foo(1)

  6. Continue from the second log in foo(1) . foo(1)的第二个日志继续。 end:1 is logged because i is equal to 1. foo(1) has resolved, go up the stack to foo(2) end:1记录因为i等于1. foo(1)已经解决,向上堆栈到foo(2)
  7. Continue from the second log in foo(2) . foo(2)的第二个日志继续。 end:2 is logged because i is equal to 2. foo(2) has resolved, go up the stack to foo(3) . end:2被记录,因为i等于2. foo(2)已经解决,向上移动堆栈到foo(3)
  8. Continue from the second log in foo(3) . foo(3)的第二个日志继续。 end:3 is logged because i is equal to 3. foo(3) has resolved and thus the call is completely resolved. end:3记录end:3 ,因为i等于3. foo(3)已经解决,因此呼叫完全解决。

This will yield: 这将产生:

begin:3 //Step 1
begin:2 //Step 2
begin:1 //Step 3
begin:0 //Step 4
end:0   //Step 5
end:1   //Step 6
end:2   //Step 7
end:3   //Step 8

Now, to answer the question: 现在,回答这个问题:

but why after foo(-1 - 1) we get the output end:0 ? 但为什么在foo(-1 - 1)之后我们得到输出结束:0?

We never call foo(-1 - 1) because foo(-1) returns immediately - it's the base case. 我们从不调用foo(-1 - 1)因为foo(-1)立即返回 - 它是基本情况。 The reason it starts logging end:i where i is ascending is because execution continues where it left off before you recursed and called foo(i - 1) . 它开始记录的原因end:i在那里i被提升是因为继续执行它离开的地方,你递归之前,呼吁foo(i - 1) Consequently, it logs end:i and then calls are resolved. 因此,它记录end:i然后调用已解决。

In fact, the function do stop when i=0 but since foo(i-1) is called before console.log('end:' + i); 实际上,当i = 0时函数会停止,但是因为foo(i-1)在console.log之前被调用('end:'+ i); the output of all the console.log('begin:' + i); 所有console.log的输出('begin:'+ i); are displayed before the end are displayed with the i value. 在显示结束之前显示i值。

Indeed, what really happens here is: 的确,这里真正发生的是:

  • foo(3) FOO(3)
    • i=3 --> display : "begin 3"; i = 3 - >显示:“开始3”;
    • Call foo(2) 打电话给foo(2)
      • i=2 --> display : "begin 2"; i = 2 - >显示:“开始2”;
      • Call foo(1) 叫foo(1)
        • i = 1 --> display : "begin 1"; i = 1 - >显示:“开始1”;
        • Call foo(0) 叫foo(0)
          • i = 0 --> display : "begin 0"; i = 0 - >显示:“开始0”;
          • Call foo(-1) --> return 调用foo(-1) - > return
          • Go back to foo(0), display "end 0" 回到foo(0),显示“结束0”
          • End of foo(0) foo结束(0)
        • Go back to foo(1), display "end 1" 回到foo(1),显示“end 1”
        • End of foo(1) ... foo结束(1)......

And so on. 等等。

this really helped me out.这真的帮助了我。 hope it helps someone out..希望它可以帮助某人..

    function foo(i) {
    console.log(i, 'called');
  if (i < 0) {
       return `${i} is returning`;
    } else {
       console.log('continue');
    }
console.log('begin:' + i);
const value = foo(i - 1);
console.log(value);
console.log(i, 'returned');
console.log('end:' + i);
}
foo(3);

every step along the way gets put in a queue [3,2,1,0] so when the program returns or exits with -1 and is able to run end it starts going back up the queue and letting the queue close or end.沿途的每一步都被放入队列 [3,2,1,0] 中,因此当程序以 -1 返回或退出并且能够运行 end 时,它开始返回队列并让队列关闭或结束。 I tried my best to explain... My big Bro helped me out.. :)我尽力解释了......我的大哥帮了我...... :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM