1

i was a reading book named async javascript , one of the example of this book tried to show that events in javascript will trigger when processor has no instruction to do in the same process . for the proof of his word he brought an example :

for (var i = 1; i <= 3; i++) {
  setTimeout(function(){ console.log(i); }, 0);
};

the output is :

4
4
4
4

everyhting is ok and i expected the result . but when i put the "console.log(i)" out of function the result will change .

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

the output is :

1
2
3

i don't know why the output is different in those examples . i know its about variable scopes , but don't know exactly the reason . i hope if someone can help.

Jafar Rasooli
  • 3,437
  • 2
  • 14
  • 13
  • 1
    @adeneo: Are you sure this is an exact duplicate? The question is asking why the output of `console.log` is different to `setTimeout`. – Matt Aug 26 '14 at 14:53
  • 1
    @Matt - Yes, it's a duplicate, the first setTimeout function creates an async function scope, while the second setTimeout does nothing, as the function isn't referenced but called directly. – adeneo Aug 26 '14 at 14:55
  • 3
    *"i don't know why the output is different in those examples"* Because you are calling `console.log(i)` **immediately** and pass the return value `undefined` to `setTimeout`. Arguments are always evaluated first, so if you have `foo(bar())`, `bar` is called first and its return value is passed to `foo`. See also http://stackoverflow.com/q/3800512/218196 – Felix Kling Aug 26 '14 at 14:56
  • @adeneo: ... and no-where in your linked duplicate is that explained. I've voted to reopen. – Matt Aug 26 '14 at 14:58
  • Made my comment an answer, but I'm sure it's a duplicate. If you find one, let me know or just close it. – Felix Kling Aug 26 '14 at 14:59
  • Possible duplicate of [Why is my function call that should be scheduled by setTimeout executed immediately](http://stackoverflow.com/questions/2037203/why-is-my-function-call-that-should-be-scheduled-by-settimeout-executed-immediat) – adeneo Aug 26 '14 at 15:04

2 Answers2

3

i don't know why the output is different in those examples

Because in the second case you are calling console.log(i) immediately and pass the return value undefined to setTimeout (instead of passing a function like in the first case).
Arguments are always evaluated first, so if you have foo(bar()), bar is called first and its return value is passed to foo.

You can verify this by adding console.log('after'); after the loop. In the first case, you should get

after
4
4
4

and in the second case, you will get

1
2
3
after

demonstrating that setTimeout is not adding anything to the event queue.

See also Calling functions with setTimeout()

i know its about variable scopes

Actually it's not, it's all about timing, the moment when console.log is executed.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
2

When you call setTimeout(expr,t), expr gets evaluated, hoping it returns a function. In your second case console.log(...) doesn't return anything, but it gets evaluated nonetheless. What you see is the side-effect of this evaluation prior to passing the result to setTimeout.

Mathias Dolidon
  • 3,775
  • 1
  • 20
  • 28