1

After reading a few links as here and here and here I'm having trouble to understand why Ver2 prints out 5 5 5 5, rather than 1 2 3 4

Ver1

for (var i = 1; i < 5; i++) {
    setTimeout(() => console.log(i), 1000)  // 5 5 5 5
}

Ver2

for (var i = 1; i < 5; i++) {
    setTimeout(() => console.log(i), 0)  // 5 5 5 5
}

Ver3

for (let i = 1; i < 5; i++) {
    setTimeout(() => console.log(i), 1000)  // 1 2 3 4 
}

In Ver3, since let is block scoped.

  1. i = 1, setTimeout(() => console.log(1), 1000) event is queued
  2. i = 2, setTimeout(() => console.log(2), 1000) event is queued
  3. i = 3, setTimeout(() => console.log(3), 1000) event is queued
  4. i = 4, setTimeout(() => console.log(4), 1000) event is queued Hence, it prints out 1 2 3 4 in sequence.

In Ver2, since var is function scoped.

  1. i = 1, setTimeout(() => console.log(i), 0) event is queued (Since delay is 0, shouldn't this print out 1 immediately?
  2. i = 2, setTimeout(() => console.log(i), 0) event is queued (prints out 2 immediately)
  3. i = 3, setTimeout(() => console.log(i), 0) event is queued (prints out 3 immediately)
  4. i = 4, setTimeout(() => console.log(i), 0) event is queued (prints out4 immediately)
  5. i = 5

After testing this out a couple of times, results consistently output 5 5 5 5 why is this the case?

0ms   Start
1ms   i = 1, queued console.log(i) after 0ms(1) (Since this is executed immediately, it should print 1??)
2ms   i = 2, queued console.log(i) after 0ms(2)
3ms   i = 3, queued console.log(i) after 0ms(3)
4ms   i = 4, queued console.log(i) after 0ms(4)
5ms   i = 5

In Ver1, since var is function scoped

  1. i = 1, setTimeout(() => console.log(i), 1000) event is queued, wait for 1000ms
  2. i = 2, setTimeout(() => console.log(i), 1000) event is queued, wait for 1000ms
  3. i = 3, setTimeout(() => console.log(i), 1000) event is queued, wait for 1000ms
  4. i = 4, setTimeout(() => console.log(i), 1000) event is queued, wait for 1000ms
  5. i = 5 After ~1000ms(or slightly over due to 4 queuing time), console should log 5 5 5 5.
0ms   Start
1ms   i = 1, queued console.log(i) after 1000ms(1)
2ms   i = 2, queued console.log(i) after 1000ms(2)
3ms   i = 3, queued console.log(i) after 1000ms(3)
4ms   i = 4, queued console.log(i) after 1000ms(4)
5ms   i = 5
1000ms console.log(i) when i = 5(1)
1001ms console.log(i) when i = 5(2)
1002ms console.log(i) when i = 5(3)
1003ms console.log(i) when i = 5(4)
jen007
  • 1,389
  • 3
  • 15
  • 19
  • 1
    My guess is setTimeout 0 adds a console.log to the next available event loop, basically JS is single threaded you've already set i to 5 by the time the callback is executed? Let me double check and I'll post an answer. – Mrk Fldig Aug 26 '19 at 17:29
  • Yes, I found setTimeOut(...,0) will defer the callback until main stack is empty. Useful link here https://www.youtube.com/watch?v=8aGhZQkoFbQ. When does this main stack get cleared out tho? Assume you'd have modules wrapping nested functions, you'd have to wait for entire modules executed before this callback being executed?? – jen007 Aug 26 '19 at 18:09
  • i in your case is in the global scope, normally callback like this have their own parameters - I'm afk at the moment but have you tried simply passing i as a parameter to the function? setTimeout((i) => console.log(i), 1000) – Mrk Fldig Aug 31 '19 at 08:56

0 Answers0