为什么 Javascript 事件循环需要在回调队列中执行函数之前完成全局执行上下文 运行

Why does the Javascript event loop require the global execution context to be finished running before executing functions in the callback queue

据我了解,在执行回调队列中的项目之前需要满足两个条件:

  1. 需要弹出调用堆栈中的所有帧
  2. 需要完成全局执行上下文中的所有代码运行

我理解这背后的原因,例如在全局执行上下文中调用了 setTimeout,但是如果在本地执行上下文中调用了 setTimeout 为什么第二个条件是必需的.难道我们不应该只需要等到调用 setTimeout 的本地执行上下文 以上 的所有帧都被弹出吗?

我认为主要的误解在于 "callstack" 这里:让我们看一下:

  (function A() {
    (function B() {
      setTimeout(function C() {
         (function D() { })();
      });
    })();
 })();

首先,代码被初始化,A 被调用,B 被调用,调用栈如下所示:

  [init] -> A -> B

现在设置超时。由于没有留下任何代码,调用堆栈展开,然后为空。

现在稍后,定时器会触发回调:

 [timer] ->

然后调用 C:

 [timer] -> C

在C里面,D会被调用:

 [timer] -> C -> D 

由于没有留下任何代码,调用堆栈再次展开。如您所见,A 和 B 已不在调用堆栈中,他们 很久以前就离开了 。因此

setTimeout was called in a local execution context. Shouldn't we only need to wait until all frames above the local execution context where the setTimeout was called are popped off?

没有什么意义,因为 "the context were the setTimeout" 是在 中执行的 最高执行上下文。

请注意,执行上下文确实有一个父执行上下文,只要它的子执行上下文存在(关闭),它就会存在,但这与调用堆栈关系不大。