3

EDIT: This question of mine has shown out to be quite ill-posed. I still believe that, especially going through the comments, it may provide some food for thoughts, but if enough votes will be reached to have it closed, I'll understand.


During some study of a very interesting treatise about ways to unwind the call stack by emulating call/cc in JavaScript (What's the difference between a continuation and a callback?) I was confronted with what seems to be a radical improvement of the way mostly used to make JS function calls asynchronous.

The most popular way is setTimeout(fun, 0). This construction takes the invocation of fun out of the current thread of execution and allows other jobs in the event queue to have their go. However, when its turn comes, fun maintains its whole call stack in all situations.

But if, as the above mentioned treatise does, the code is changed to setTimeout.bind(null, fun, 0) and we are programming in continuation-passing style (no return instructions to remember), then the call stack of fun is cleared and brought back to depth 1.

It is possible to see all this at work in an example. Verified in Chrome, FF, IE, Opera.

The sample HTML page is very simple to download and run in the browser with the developer tools open. There are two pausing instructions at rows 18 and 42, where you can observe the differences between the call stacks maintained by the two invocations of setTimeout.

The question is: how come that setTimeout.bind() behaves so radically different from a plain setTimeout invocation? Can someone illustrate what is going on?

Community
  • 1
  • 1
Marco Faustinelli
  • 3,734
  • 5
  • 30
  • 49
  • 1
    what makes you think `setTimeout(fun, 0)` maintains a deep stack? – Amit Nov 01 '15 at 22:48
  • 1
    You are not using `setTimeout(fun, 0)` as would be proper, but actually you're doing `setTimeout(fun(), 0)` (with `.apply`, but still). Should be obvious by now why the call stack is still there… – Bergi Nov 01 '15 at 23:48
  • 1
    @Bergi - OK, I think I got it. I see now that `setTimeout.bind(null, this, 0).apply(null, arguments)` is __lazy__, whereas `setTimeout(this.apply(null, arguments), 0)` is *not*. In the second case all `this.apply`'s are running inside the same execution context and therefore the last one carries along the whole call stack. – Marco Faustinelli Nov 02 '15 at 08:16
  • @Amit - I was misguided by the wrong interpretation I was giving to this whole matter. I thank you for your socratic stance? :-) – Marco Faustinelli Nov 02 '15 at 08:21

0 Answers0