Recently i have been struggling to understand recursion very well and how everything actually works, so i wrote this js function
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". 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.
6 Answers 6
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. No what's the value of times in there? The major point to understand is that every call maintains its local variables - and in the second call, times was 2. Then after logging it returns from the second call to the first call. There, times had the value 3, which gets logged. Then it finally returns from the first call to the call site checkScope(3) after which the script ends.
Comments
It is related with the order of console.log() and checkScope() function call. Since you are calling the checkScope() function first, it will end up console logging the last item.
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);
Comments
It's simple. See, you invoke console.log after the checkScope call on the 4th line. This causes all the console.log calls to be postponed to the time when recursion resolves (times == 1). So here what happens:
- checkScope(3);
- checkScope(2); // at 4th line
- checkScope(1); // at 4th line
- console.log(
Times is ${times}); // with 1 at 2nd line - console.log(
Times is ${times}) // with 2 at 5th line - console.log(
Times is ${times}) // with 3 at 5th line
Comments
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
Comments
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.
Comments
So let's take it step by step, you call checkScope(3)
- checkScope(3) is called
- if (3 == 1) turns false so we go to the else block of code
- the first line in the else block calls checkScope(3-1) *
- checkScope(2) is called
- if (2 == 1) turns false so we go to the else block of code
- the first line in the else block calls checkScope(1) **
- checkScope(1) is called
- if(1==1) is true so we console.log("Time is 1"), the checkScope(1) function is finished.
- we return to the ** because our checkScope(2) instance hasn't ended yet
- we console.log("Time is 2") so the checkScope(2) now is finished and we go to *.
- we console.log("Time is 3") and the checkScope(3) now is finished.
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. 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). So, at the step 4 when checkScope(2) is called the call stack would be:
- checkScope(2)
- checkScope(3)
And at the step 7 the call stack would be:
- checkScope(1)
- checkScope(2)
- checkScope(3)
At step 8 the call stack is:
- checkScope(2)
- checkScope(3)
At step 10 the call stack:
- checkScope(3)
And when we reach step 11 the call stack is empty because all the functions called have now been terminated.
ifstatement, addconsole.log(times);- you'll see it's called 3, 2, 1 THEN it starts outputting per yourifconditions. This is because (as @Will says), you're callingcheckScopebefore you output anything. See this fiddle: jsfiddle.net/cale_b/mwytkjhz