简体   繁体   English

递归过程中的函数调用

[英]Functions call during recursions

Recently i have been struggling to understand recursion very well and how everything actually works, so i wrote this js function 最近我一直在努力地很好地理解递归以及一切实际上如何工作,所以我写了这个js函数

function checkScope(times){
    if(times == 1){
        console.log(`Times is ${times}`);
    }else{
        checkScope(times-1);
        console.log(`Times is ${times}`)
    }
}

To my understanding, i believed if i invoked this function with: 据我了解,我相信是否可以通过以下方式调用此功能:

checkScope(3)

Theb the first statement in the else block is firstly executed and the function is called again, then same thing happen and this time the variable times = 1 so i should get a log of "Times is 1". 然后,首先执行else块中的第一条语句,然后再次调用该函数,然后发生相同的事情,这次变量时间= 1,因此我应该得到“时间为1”的日志。 And maybe when control is transferred back to the calling function, the last line of code is executed with: 也许当控制权转移回调用函数时,使用以下代码执行最后一行代码:

Times is [I dont know what times should be at this time :(]

But when i run this, i end up getting 但是当我运行它时,我最终得到了

Times is 1
Times is 2
Times is 3

as my output, please i need an explanation to this. 作为我的输出,请对此进行解释。

It is related with the order of console.log() and checkScope() function call. 它与console.log()checkScope()函数调用的顺序有关。 Since you are calling the checkScope() function first, it will end up console logging the last item. 由于您是先调用checkScope()函数,因此它将结束控制台并记录最后一项。

So you should replace the order of rows as follows: 因此,您应该按以下方式替换行的顺序:

 function checkScope(times){ if(times == 1){ console.log(`Times is ${times}`); }else{ console.log(`Times is ${times}`) checkScope(times-1); } } checkScope(3); 

For better understanding, check this one. 为了更好地理解,请选中此复选框。

 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); 

And maybe when control is transferred back to the calling function… 也许当控制权转移回调用函数时……

…then you need to have remembered which that was. …那么您需要记住那是。 In this case, the third call (that logged 1 ) does return back to the second call, which continues with the console.log statement in there. 在这种情况下,第三个调用(记录为1 )确实返回到第二个调用,第二个调用在那里继续执行console.log语句。 No what's the value of times in there? 不, times的价值何在? The major point to understand is that every call maintains its local variables - and in the second call, times was 2 . 要理解的主要要点是, 每个调用都维护其局部变量 -在第二个调用中, times2 Then after logging it returns from the second call to the first call. 然后在记录后,它从第二个呼叫返回到第一个呼叫。 There, times had the value 3 , which gets logged. 在那里, times的值为3 ,它被记录下来。 Then it finally returns from the first call to the call site checkScope(3) after which the script ends. 然后,它最终从第一个调用返回到调用站点checkScope(3)此后脚本结束。

It's simple. 这很简单。 See, you invoke console.log after the checkScope call on the 4th line. 请参见,您在第四行的checkScope调用之后调用console.log This causes all the console.log calls to be postponed to the time when recursion resolves ( times == 1 ). 这将导致所有console.log调用都推迟到递归解析的时间( times == 1 )。 So here what happens: 所以这里发生了什么:

  1. checkScope(3); checkScope(3);
  2. checkScope(2); checkScope(2); // at 4th line //在第四行
  3. checkScope(1); checkScope(1); // at 4th line //在第四行
  4. console.log( Times is ${times} ); console.log( Times is ${times} ); // with 1 at 2nd line //第二行有1
  5. console.log( Times is ${times} ) // with 2 at 5th line console.log( Times is ${times} )//第5行有2
  6. console.log( Times is ${times} ) // with 3 at 5th line console.log( Times is ${times} )//在第5行有3

You can always put a debugger to see the flow, anyways check below explanation 您可以随时放置调试器以查看流程,无论如何请检查以下说明

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

I hope this helps you to understand the code 我希望这可以帮助您理解代码

So let's take it step by step, you call checkScope(3) 因此,让我们逐步介绍一下,您调用checkScope(3)

  1. checkScope(3) is called checkScope(3)被调用
  2. if (3 == 1) turns false so we go to the else block of code 如果(3 == 1)变为false,那么我们转到else代码块
  3. the first line in the else block calls checkScope(3-1) * else块中的第一行调用checkScope(3-1)*
  4. checkScope(2) is called checkScope(2)被调用
  5. if (2 == 1) turns false so we go to the else block of code 如果(2 == 1)变为false,那么我们转到else代码块
  6. the first line in the else block calls checkScope(1) ** else块中的第一行调用checkScope(1)**
  7. checkScope(1) is called checkScope(1)被调用
  8. if(1==1) is true so we console.log("Time is 1"), the checkScope(1) function is finished. 如果(1 == 1)是true,那么我们console.log(“ Time is 1”),checkScope(1)函数完成。
  9. we return to the ** because our checkScope(2) instance hasn't ended yet 我们返回**,因为我们的checkScope(2)实例尚未结束
  10. we console.log("Time is 2") so the checkScope(2) now is finished and we go to *. 我们console.log(“ Time is 2”),所以checkScope(2)现在完成了,我们转到*。
  11. we console.log("Time is 3") and the checkScope(3) now is finished. 我们console.log(“ Time is 3”)并且checkScope(3)现在完成。

In general what you should keep in mind is that there is a thing called "call stack". 通常,您应该牢记的是有一个叫做“调用栈”的东西。 You can think of it as a stack where all functions called go. 您可以将其视为所有调用go的函数的堆栈。 The function on top is the one currently executed. 最上面的功能是当前执行的功能。 Once a function is completed it goes out of the stack and then the next function is on top. 一旦完成一个功能,它就会从堆栈中移出,然后将下一个功能放在最上面。

In checkScope(3) when a new instance of checkScope is called it is put over checkScope(3). 在checkScope(3)中,当调用checkScope的新实例时,将其置于checkScope(3)之上。 So, at the step 4 when checkScope(2) is called the call stack would be: 因此,在步骤4调用checkScope(2)时,调用堆栈为:

  1. checkScope(2) checkScope(2)
  2. checkScope(3) checkScope(3)

And at the step 7 the call stack would be: 在第7步中,调用堆栈为:

  1. checkScope(1) checkScope(1)
  2. checkScope(2) checkScope(2)
  3. checkScope(3) checkScope(3)

At step 8 the call stack is: 在步骤8,调用堆栈为:

  1. checkScope(2) checkScope(2)
  2. checkScope(3) checkScope(3)

At step 10 the call stack: 在步骤10,调用堆栈:

  1. checkScope(3) checkScope(3)

And when we reach step 11 the call stack is empty because all the functions called have now been terminated. 当我们到达步骤11时,调用堆栈为空,因为所有已调用的函数现已终止。

This made it clearer 这使它更清晰

So, since none of the previous function calls before times == 1 has gotten to their last lines, after times == 1 then all other functions execute their last lines of codes which is the console.log() line with their times variable value. 因此,由于times == 1之前的所有函数均未到达其最后一行,因此times == 1之后,所有其他函数均执行其最后代码行,即console.log()行,其times变量值为。

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

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