11
timer =  window.setTimeout(function () {
    //do something
    window.setTimeout(arguments.callee, 1000);
}, 1000);

the result is that these codes work well.

but why doesn't it cause the error below?

Maximum Call Stack Size Exceeded

when debugging it, find the variable scope don't include the scope of previous executed "setTimeout function"

Who can explain this?

with documentation preferably.

2
  • 1
    This is a recursive call though, it's self referential. While we're here - OP don't use arguments.callee if you want a function expression and you want to call it recursively - name it: setTimeout(function foo(){ setTimeout(foo,1000);}) Commented Jul 8, 2014 at 11:53
  • 1
    yes,the arguments.callee is dumped in the future.but in on screen, the new Function () {} ,you must use arguments.callee to get the function Commented Jul 8, 2014 at 12:04

2 Answers 2

13

setTimeout is asynchronous (it returns before executing the callback), and the callback will be executed on a new, empty stack frame. That's the whole purpose. It will never overflow the stack.

It is not a recursive call, for which scope (in case of a non-tail-call-optimized function) would need to be retained. But that would also mean that the function became blocking, which is not what you want.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh, he is asking why it doesn't cause a StackOverflow. I totally missed that. You might want to mention that you can get the stack trace in newer versions of chrome that have async stack traces.
are there documents to explain what you say?
@SKing7 there is the DOM timers API that specifies how it should work, and I can send you a link to the implementation in chrome - but that's not too helpful. whatwg.org/specs/web-apps/current-work/multipage/timers.html here is the timers API.
@SKing7: I just found developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop. If you're looking for something official, the HTML5 timer spec might be able to explain this as well, but in very complicated terms only.
3

This is because the Timeout callbacks are not stored in the stack as you are assuming: there are in a queue, waiting to be executed in its own stack. And in your code the queue is filled when the previous execution is completed, so the queue is not growing.

UPDATE: You can check the specs here, but I'm copying the text:

The setTimeout() method must run the following steps:

  1. Let handle be a user-agent-defined integer that is greater than zero that will identify the timeout to be set by this call.

  2. Add an entry to the list of active timeouts for handle.

  3. Get the timed task handle in the list of active timeouts, and let task be the result.

  4. Get the timeout, and let timeout be the result.

  5. If the currently running task is a task that was created by the setTimeout() method, and timeout is less than 4, then increase timeout to 4.

  6. Return handle, and then continue running this algorithm asynchronously.

  7. If the method context is a Window object, wait until the Document associated with the method context has been fully active for a further timeout milliseconds (not necessarily consecutively).

  8. Otherwise, if the method context is a WorkerUtils object, wait until timeout milliseconds have passed with the worker not suspended (not necessarily consecutively).

  9. Otherwise, act as described in the specification that defines that the WindowTimers interface is implemented by some other object.

  10. Wait until any invocations of this algorithm started before this one whose timeout is equal to or less than this one's have completed.

    Optionally, wait a further user-agent defined length of time.

1 Comment

are there documents to explain what you say?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.