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

为什么Javascript事件循环要求在执行回调队列中的函数之前完成全局执行上下文的运行,javascript,event-loop,Javascript,Event Loop,我的理解是,在执行回调队列中的项目之前,需要满足两个条件: 需要弹出调用堆栈中的所有帧 全局执行上下文中的所有代码都需要完成运行 例如,如果在全局执行上下文中调用了setTimeout,我理解其背后的原因,但是如果在本地执行上下文中调用了setTimeout,为什么第二个条件是必要的。我们是否只需要等到调用了setTimeout的本地执行上下文中的所有帧都弹出后,就可以了?我认为主要的错误理解在于这里的“调用堆栈”:让我们看一下: (function A() { (function

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

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

  • 例如,如果在全局执行上下文中调用了
    setTimeout
    ,我理解其背后的原因,但是如果在本地执行上下文中调用了
    setTimeout
    ,为什么第二个条件是必要的。我们是否只需要等到调用了
    setTimeout
    的本地执行上下文中的所有帧都弹出后,就可以了?

    我认为主要的错误理解在于这里的“调用堆栈”:让我们看一下:

      (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是在本地执行上下文中调用的。难道我们不应该只需要等到调用setTimeout的本地执行上下文之上的所有帧都弹出吗

    没有什么意义,因为“上下文是setTimeout”是在最上面的执行上下文中执行的


    请注意,执行上下文确实有一个父执行上下文,它将与子执行上下文一样长(闭包),但是这与调用堆栈几乎没有关系。

    第一个条件意味着第二个条件(如果我理解正确的话)?“全局执行上下文”是什么意思?没错。为了完整性,我添加了这两个条件。所谓全局执行上下文,我指的是没有在函数内部运行的代码(即,永远不会弹出的框架)。“全局执行上下文”执行只是队列上的一个任务,如果这样做,事件循环将继续。