【发布时间】:2016-04-14 14:28:54
【问题描述】:
我已经阅读了几个关于事件循环的帖子/SO 线程,根据MDN's article,
当堆栈为空时,从队列中取出一条消息并 已处理。
作为一个 JS 新手,我仍然感到困惑的是——调用堆栈究竟什么时候变成“空”的?例如,
<script>
function f() {
console.log("foo");
setTimeout(g, 0);
console.log("foo again");
}
function g() {
console.log("bar");
}
function b() {
console.log("bye");
}
f();
/*<---- Is the stack empty here? */
b();
</script>
正确的执行顺序是foo - foo again - bye - bar。
但是今天我开始思考:在退出f() 调用后,堆栈在技术上不是空的吗?我的意思是,此时我们不在任何函数内部,也没有开始任何新的执行,所以在转到 b() 之前,不应该处理 setTimeout 调用消息(已立即排队) ,并给出foo-foo again-bar-bye的顺序?
如果我们有 a million lines of code 或一些密集的计算要执行,而 setTimeout(func, 0) 只是在队列中等待多长时间?
【问题讨论】:
-
我能想到的最好的解释方法是,在代码完成运行所有相关路径之前,调用堆栈不是空的。 setTimeout 为 0 只会将您的代码推送到堆栈的末尾,即:在 b() 之后。
-
还有
b需要执行,所以f之后的堆栈不为空。b之后还有什么可做的? -
@Jacques 我认为堆栈的概念应该根据函数调用/帧来理解,而不是还有代码要执行......我从MDN example 和this demo...
-
这个视频对这个话题很有帮助:vimeo.com/96425312 简而言之,超时事件在剩余的脚本执行之后才会发生。
-
由于全局环境是一个执行环境,我想它在脚本最初加载时位于调用堆栈的底部。
标签: javascript asynchronous concurrency settimeout event-loop