3

The following code has a new callstack when the debugger fires in d (jsfiddle here)

function c() {
    setTimeout( d, 1000 );
}

function d() {
    debugger;   
}

c();

If we modify the code to use setTimeout( d(), 1000 ); which has brackets (parenthesis:)

function c() {
    setTimeout( d(), 1000 );
}

function d() {
    debugger;   
}

c();

then the callstack has both c() and d() (jsfiddle here). Why?

Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228
  • 2
    `d` evaluates to a function-object. Using the function-application operator, `()`, on the function-object (which resulted from the evaluation of `d`) invokes it immediately and evaluates to the result of said function (undefined in this case), which is then passed as an argument to `setTimeout`. That is, it is equivalent to: `var r = d(); setTimeout(r, 1000);` or, in this case, `d(); setTimeout(undefined, 1000)`. –  Nov 09 '11 at 00:49
  • Dup of [Why is my function call scheduled by setTimeout executed immediately?](http://stackoverflow.com/questions/2037203/), [Calling functions with setTimeout()](http://stackoverflow.com/questions/3800512/), [Javascript setTimeout() is ignoring the timeout length](http://stackoverflow.com/questions/4120781/), [why is this setTimeout not working](http://stackoverflow.com/questions/5116223/), [Why is the method executed immediately when I use setTimeout?](http://stackoverflow.com/questions/7137401/) – outis Nov 09 '11 at 21:42
  • @outis I don't think it is a duplicate, very similar once you have the knowledge but this one relates to the callstack generated, the others do not. – Aran Mulholland Nov 10 '11 at 01:13
  • @Aran: It's exactly the same question, though stated differently. An immediate function call is the same as a frame being pushed on the call-stack while another is still active. The mention of call-stacks merely couches the question in terms of a particular computational model. If anything, this is a more limited statement of the question. – outis Nov 10 '11 at 04:21
  • @outis i still think it is a valid question, and having a question asked in more than one way just expands the possibility of a greater understanding of the problem space. i was looking for a way to start a new callstack, i ended up understanding setTimeout better. once you know the answer you could see it as a duplicate, before then it is totally different and relates to a different problem. – Aran Mulholland Nov 10 '11 at 05:51
  • @Aran: I'm not saying the question is invalid, and I'm not saying you shouldn't have asked it. "Close as duplicate" doesn't mean anything like "shouldn't exist". SO questions are supposed to be generally applicable, not just to help one person with one problem. As such, it's better to have one question as the canonical representation, with duplicates acting as pointers to it. Marking questions as duplicates helps focus attention, reducing "echoes" as it were. Too many exact duplicates make it harder to find a question when you search the site. – outis Nov 10 '11 at 07:48
  • ... As for parentheses causing functions to be called, it's entirely separate from the behavior of `setTimeout`; the former has nothing to do with the latter. Parentheses invoke a function, no matter the context. Moreover, while thinking in terms of call stacks may be useful at one stage of your development, there are more general ideas that are more useful (synchronous vs. asynchronous invocation, continuations). – outis Nov 10 '11 at 07:59

3 Answers3

10

You are not passing setTimeout the function d in the second example; you are instead passing d(), which is the result of calling d.

The result of calling d is undefined since it returns nothing, which converts to the string "undefined", which is then evaled, doing... precisely nothing.


With regard to callstacks, since you are calling d inside of c, that is why you see c in the callstack. To clarify, your second example is the same as

function c() {
    var temp = d();
    setTimeout(temp, 1000);
}

function d() {
    debugger;   
}

c();
Domenic
  • 110,262
  • 41
  • 219
  • 271
2

SetTimeout takes a function argument. If you pass a string, it acts like eval. If you invoke the function, like you did, it fires immediately then setTimeout fires with the results in a new call stack.

AutoSponge
  • 1,444
  • 10
  • 7
1

Because in the first example you are passing a function pointer as the thing to execute in 1 second. In the second example you have already executed d, and you are passing the results of d() to setTimeout to call in 1 second.

Scott A
  • 7,745
  • 3
  • 33
  • 46