为什么setTimeout调用的函数没有callstack限制?

时间:2014-07-08 11:47:50

标签: javascript browser settimeout

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

结果是这些代码运作良好。

但为什么没有导致下面的错误?

  

超出最大调用堆栈大小

调试时,找到变量范围,不包括先前执行的范围" setTimeout函数"

谁可以解释一下?

最好是文档。

2 个答案:

答案 0 :(得分:7)

setTimeout是异步的(它在执行回调之前返回),并且回调将在新的空堆栈帧上执行。这就是整个目的。

这不是递归调用,需要保留范围(在非tail-call - 优化函数的情况下)。但这也意味着功能变得阻塞,这不是你想要的。

答案 1 :(得分:0)

这是因为Timeout回调没有像你假设的那样存储在堆栈中:队列中等待在自己的堆栈中执行。在您的代码中,队列在前一次执行完成时被填充,因此队列不会增长。

更新:您可以查看规范here,但我正在复制文字:

  

setTimeout()方法必须运行以下步骤:

     
      
  1. 让handle成为用户代理定义的大于零的整数   这将标识此次调用设置的超时。

  2.   
  3. 在句柄的活动超时列表中添加一个条目。

  4.   
  5. 在活动超时列表中获取定时任务句柄,然后让   任务就是结果。

  6.   
  7. 获取超时,并将超时作为结果。

  8.   
  9. 如果当前正在运行的任务是由。创建的任务   setTimeout()方法,并且超时小于4,然后增加   超时到4。

  10.   
  11. 返回句柄,然后继续运行此算法   异步。

  12.   
  13. 如果方法上下文是Window对象,请等到Document   与方法上下文相关联已经完全活跃了   进一步超时毫秒(不一定是连续的)。

  14.   
  15. 否则,如果方法上下文是WorkerUtils对象,请等待直到   在没有暂停工作的情况下超时毫秒(不是   必须连续)。

  16.   
  17. 否则,按照规范中描述的那样定义   WindowTimers接口由其他一些对象实现。

  18.   
  19. 等到此算法的任何调用在此之前启动   其超时时间等于或小于此时间已完成。

         

    (可选)等待另一个用户代理定义的时间长度。

  20.