JS callstack总是至少有一个框架吗?

时间:2014-12-17 15:42:07

标签: javascript callstack event-loop

我最近看到一个presentation on the JS event loop,坦白地说,这很棒,但我现在对JS调用堆栈有一个挥之不去的问题。如果你考虑全局执行上下文,比如main(),main()从未解决过?我的理由是,如果是,那么JS程序就完整了,不会发生回调。

- 修改

我的主要兴趣是如何表示与回调队列相关的调用堆栈。如果在将新帧推入堆栈之前,事件循环被称为等待调用堆栈为空,那么循环将等待直到程序完成,并且回调不会产生任何影响。

我想这意味着事件循环等待只剩下一个帧(主执行上下文),而不是没有帧。

2 个答案:

答案 0 :(得分:3)

  

如果您将全局执行上下文视为main()

没有。 main不是global execution context,它是最初在该上下文中运行的代码。全局环境是 - 通过关闭 - 在全局代码运行后仍然保留用于未完成的回调,在程序完成之前它不会被垃圾收集。

  

是main()从未解决过吗?

当然是。 main()invocation of any global code - 基本上,当您在网页中加载脚本并执行时(是的,这可能会多次发生)。或者告诉节点执行的全局程序。一旦该代码完成运行,它确实会弹出堆栈,正如您在会谈动画中所看到的那样。它不会继续运行",因为这会阻止事件循环。

  

我的理由是,如果是,那么JS程序就完成了,不会发生回调。

没有。该脚本可能已经完成,是的,但您的程序(浏览器环境,节点等)尚未完成。事件循环仍在旋转(或者,确切地说:刚开始旋转)。

事件循环将查看正在进行的异步任务(XHR,超时,文件IO等),并注意到仍有一些工作正常。该程序不会退出。一旦这些任务中的一个(或多个)完成,他们就会将回调放在回调队列中,在那里它被事件循环拾取,并通过在全新的调用堆栈上执行它来处理。当该堆栈再次为空时,事件循环将重新处于控制状态,并从队列中获取回调,直到它为空。然后,它再次查看是否仍有正在进行的任务(其中一个回调可能产生了新的任务),并且只有当没有任务时,程序才会真正结束,并且全局环境可能会被破坏。

所以是的,确实有时候执行一个javascript程序,其中callstack是空的,只有事件循环快乐地旋转 - 实际上,大多数情况下都是这种情况。

答案 1 :(得分:2)

正如您所说,main()是全局执行上下文。它还活着,直到:

  • 如果您在浏览器中关闭标签
  • 如果您在服务器(如节点)
  • 上,则会终止该过程
  • 标签/进程崩溃

因此,除非上述用例之一发生,否则运行时仍处于活动状态,事件循环(将处理任务队列)也是如此。