timer = window.setTimeout(function () {
//do something
window.setTimeout(arguments.callee, 1000);
}, 1000);
结果是这些代码运行良好。
但为什么它不会导致下面的错误?
超出最大调用堆栈大小
调试的时候发现变量作用域不包括之前执行的“setTimeout函数”的作用域
谁能解释一下?
最好有文档。
timer = window.setTimeout(function () {
//do something
window.setTimeout(arguments.callee, 1000);
}, 1000);
结果是这些代码运行良好。
但为什么它不会导致下面的错误?
超出最大调用堆栈大小
调试的时候发现变量作用域不包括之前执行的“setTimeout函数”的作用域
谁能解释一下?
最好有文档。
setTimeout
是异步的(它在执行回调之前返回),并且回调将在一个新的空堆栈帧上执行。这就是全部目的。它永远不会溢出堆栈。
它不是递归调用,需要保留其作用域(在非尾调用优化函数的情况下)。但这也意味着函数变得阻塞,这不是你想要的。
这是因为 Timeout 回调没有像您假设的那样存储在堆栈中:有一个队列,等待在自己的堆栈中执行。并且在您的代码中,队列在前一次执行完成时被填满,因此队列没有增长。
更新:您可以在此处查看规格,但我正在复制文本:
setTimeout() 方法必须运行以下步骤:
令句柄是一个用户代理定义的大于零的整数,用于标识此调用设置的超时时间。
将条目添加到句柄的活动超时列表中。
获取活动超时列表中的定时任务句柄,并让任务成为结果。
获取超时,并让超时成为结果。
如果当前运行的任务是 setTimeout() 方法创建的任务,并且 timeout 小于 4,则将 timeout 增加到 4。
返回句柄,然后继续异步运行该算法。
如果方法上下文是 Window 对象,则等待与方法上下文关联的 Document 完全激活再超时毫秒(不一定是连续的)。
否则,如果方法上下文是 WorkerUtils 对象,请等待超时毫秒已过且工作器未挂起(不一定连续)。
否则,按照定义 WindowTimers 接口由其他对象实现的规范中的描述进行操作。
等到此算法的任何调用在超时等于或小于此算法的调用完成之前开始。
或者,等待用户代理定义的进一步时间长度。