0

I can't find the answer to this question on any other previously asked question.

This will alert 5 times, displaying the numbers 1 to 5.

for (i = 1; i <= 5; i++) {
 alert(i)
}

This will alert 5 times, displaying the number 6 every time. I understand that it will display the same number 5 times but why does it display 6 instead of 5?

for (i = 1; i <= 5; i++) {
 setTimeout(function(){
  alert(i)
 });
}
Boann
  • 48,794
  • 16
  • 117
  • 146
  • 4
    Because you incremented `i` to `6`. The last `i++` is the one that causes the `i <= 5` to fail, and your `alert` calls happen after the loop. –  Apr 21 '18 at 17:47
  • @Nina: That's not a duplicate. –  Apr 21 '18 at 17:48
  • @CrazyTrain, why not? – Nina Scholz Apr 21 '18 at 17:50
  • If you use let when you set the i variable, it will behave as you expect. `for (let i = 1; i<=5;i++)` – pigeontoe Apr 21 '18 at 17:51
  • @NinaScholz: Because he wrote that he understands that the same number will be alerted `5` times, but that he wants to know why the number alerted is `6` instead of `5`. In other words, he knows that the variable is shared by all the callbacks, which run after the loop is done, but is confused about the final incrementing of `i`. –  Apr 21 '18 at 17:51
  • @CrazyTrain , yes the condition failed when it get incremented to 6 so it should not enter the inner part of loop just like it do in earlier example – Dipesh rana Apr 21 '18 at 17:55
  • 2
    It doesn't enter the inner part. The `alert()` only runs five times, but `i` was incremented six times. The loop was not entered after the sixth increment, which is why you do see `6` as the value but only alerted five times. –  Apr 21 '18 at 17:56
  • @NinaScholz: That's not a duplicate. –  Apr 21 '18 at 17:57
  • @CrazyTrain then why its different on first example, little bit confused, I am alerting it inside loop in second example too – Dipesh rana Apr 21 '18 at 18:00
  • @NinaScholz , I was not able to find the answer to this question, thats why I asked it here – Dipesh rana Apr 21 '18 at 18:03
  • 1
    Because in the first example, the alerts run inside the loop, and not after the loop is done. Because the last `i++` happens *after* the last loop body execution, it's new value is never seen. Put another `alert(i)` after the loop to see what I mean. –  Apr 21 '18 at 18:04
  • 1
    @Dipeshrana, never mind. it's dupe, because you use a closure over a variable which has the last value of 6 of the `for` loop and this value is used in the timeout. – Nina Scholz Apr 21 '18 at 18:05
  • @CrazyTrain , but why alert runs after the loop is done, I placed the alert inside loop in this example too, right ? – Dipesh rana Apr 21 '18 at 18:06
  • Well, you said you're clear on why you get the same number over and over instead of a different value for each iteration right? Yet the code is inside the loop, so why are you not also then surprised that it doesn't give `1`, `2`, `3`, `4`, `5`? –  Apr 21 '18 at 18:08
  • @NinaScholz: That's not a duplicate. Even though the OP is confused about things, the way the question is phrased, it's not asking why the value isn't `1` through `5`, but rather why the value is always `6` instead of always `5`. –  Apr 21 '18 at 18:10
  • The `i++` is executed, And after 1 second that is the value `i` got. – deEr. Apr 21 '18 at 18:10
  • @CrazyTrain Still a closure. Because `setTimeout` is a `function`. Which remembers. – deEr. Apr 21 '18 at 18:11
  • @NinaScholz: If that was a legitimate duplicate, then the expectation would be a unique alerted value for each iteration. –  Apr 21 '18 at 18:11
  • the last check of `i <= 5` takes `6` as value and exit the loop. – Nina Scholz Apr 21 '18 at 18:11
  • @AjAX. I didn't say it wasn't a closure. –  Apr 21 '18 at 18:11
  • @CrazyTrain Just saying, might be a duplicate. %)P – deEr. Apr 21 '18 at 18:12
  • @CrazyTrain i thought its happening because the loop doesnt wait for seTimeout and runs again, I think I need to study about it – Dipesh rana Apr 21 '18 at 18:13
  • @AjAX.: The OP is definitely confused about closures, but the expectation described in the question is not the expectation described in the duplicate, which would be required for it to actually be a duplicate. –  Apr 21 '18 at 18:13
  • @Dipeshrana: Right, the loop doesn't wait. The `setTimeout` callbacks run after the loop is finished. That's why you get the same number over and over. –  Apr 21 '18 at 18:14
  • It does — not — wait for `setTimeout`. That is why it is happening. The loop is — not — entered. But 6 made out of `i++`. – deEr. Apr 21 '18 at 18:14
  • @CrazyTrain , AjAx I have read about call back functions, its a child function which executes after parent function finish, right ? – Dipesh rana Apr 21 '18 at 18:17
  • @NinaScholz: That's not a duplicate. Its explanations describe the difference between getting `1,2,3,4,5` and `6,6,6,6,6`, not between getting `5,5,5,5,5` and `6,6,6,6,6`. –  Apr 21 '18 at 18:17
  • 1
    Overall the question is why `i++` is still hit. After `i==5` is hit. – deEr. Apr 21 '18 at 18:18
  • @Dipeshrana: "child" and "parent" are not the typical terms used, but basically yes, at least in this case. So since you know that the callbacks run sometime after the "parent" function has finished, then you already know that it also runs after the loop is finished. –  Apr 21 '18 at 18:19
  • so for is a function and setTimeout is callback function, right ? – Dipesh rana Apr 21 '18 at 18:19
  • 1
    @Dipeshrana: `for` isn't a function. `setTimeout` is function. The first *argument* passed to the `setTimeout` function is the callback function. –  Apr 21 '18 at 18:20
  • @AjAX. , no I know why i++ hits to 6, what i was asking that i == 6 should be false and should not enter the loop – Dipesh rana Apr 21 '18 at 18:21
  • from [`for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for), *final-expression*: "An expression to be evaluated at the end of each loop iteration. This occurs before the next evaluation of condition. Generally used to update or increment the counter variable." – Nina Scholz Apr 21 '18 at 18:22
  • Ok. Got it. `5<=5` and all numbers below like `1<=5` are `true`. Only `i++` till 6 gives `false`. `i++` is — not — hit after that. True? – deEr. Apr 21 '18 at 18:22
  • @CrazyTrain if the alert run after the loop is finished then why 6 is alerting 5 times, shouldnt it alert 1 time then ? – Dipesh rana Apr 21 '18 at 18:23
  • No. That is due to closure again. – deEr. Apr 21 '18 at 18:24
  • @CrazyTrain The value of i after the loop finishes is 6, at which point the loop exits. The alert is alerting to the value of i, which after 1 second is 6. it is not evaluating the value of i because it has not been told to do so. – Wayne Apr 21 '18 at 18:24
  • 1
    @Dipeshrana: No, what `setTimeout` does is it schedules your code to run in the future. Because you called `setTimeout` five times, it will invoke the callback function you provided each time. So five calls to `setTimeout` tells it to schedule five events. Those five events invoke the five separate callback functions that were given during each iteration. –  Apr 21 '18 at 18:26
  • @Wayne: You're addressing the wrong person. –  Apr 21 '18 at 18:26
  • @Wayne seconds dont matter here, even if I set the seTimeout delay to 0 second same result will occur – Dipesh rana Apr 21 '18 at 18:27
  • @Dipeshrana It is always run afterwards even with 0 ms. That's how JavaScript and the event loop work. – Ivar Apr 21 '18 at 18:28
  • @CrazyTrain now I am getting the things, what topic I should read to be more clear on these things ? – Dipesh rana Apr 21 '18 at 18:29
  • `setTimeout(function,0)` got something to do with the `single-treadedness` of Javascript. It will just be pushed down the line. – deEr. Apr 21 '18 at 18:29
  • 1
    @Dipeshrana, just the dupe target and the docu about `for` syntax. – Nina Scholz Apr 21 '18 at 18:29
  • @AjAX. oh ok, thanks buddy – Dipesh rana Apr 21 '18 at 18:31
  • @NinaScholz I think i am aware about how for works, but the closure is not i am much aware about, I will read about it , thanks – Dipesh rana Apr 21 '18 at 18:32
  • thank you guys to be so supportive , specially @CrazyTrain and others too.. – Dipesh rana Apr 21 '18 at 18:33
  • @NinaScholz Don’t call it a “dupe”. [Das heißt ”der Betrogene & der Tölpel”.](https://dict.leo.org/englisch-deutsch/dupe) Call it ”dupli”. %)P – deEr. Apr 21 '18 at 18:33
  • @NinaScholz: That's not a duplicate. Its explanations describe the difference between getting `1,2,3,4,5` and `6,6,6,6,6`, not between getting `5,5,5,5,5` and `6,6,6,6,6`. Thankfully Dipesh is a faster learner, so he will still be able to figure this out in spite of you preventing answers that are actually relevant to the question. –  Apr 21 '18 at 19:08
  • @Dipeshrana true, but easier to understand seconds than javascript is single threaded and will not run a setTimeout until after the loop is finished. – Wayne Apr 21 '18 at 19:34
  • You call `setTimeout` 5 times, setting up 5 alerts to display after the loop, by which time the value of `i` will be 6. – Boann Apr 22 '18 at 15:58

0 Answers0