乐趣区

关于javascript:点击触发事件和JS触发事件在EventLoop上的区别

问题

话不多说,间接上代码剖析:

<div class="outer">
  <div class="inner"></div>
</div>
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

new MutationObserver(function () {console.log('mutate');
}).observe(outer, {attributes: true})

function onClick() {console.log('click');

  setTimeout(function () {console.log('timeout')
  }, 0);

  Promise.resolve().then(function () {console.log('promise')
  });

  outer.setAttribute('data-random', Math.random());
}

outer.addEventListener('click', onClick);
inner.addEventListener('click', onClick);

// inner.click();

对于以上代码,间接在页面点击触发,会打印出什么样的日志程序?
如果在代码最初应用 js 触发:inner.click(),又会是怎么的打印程序呢?

解答

点击 outer 的打印后果:click promise mutate timeout
就是失常的 eventloop 程序,着重说 inner 的后果。

点击 inner 的打印后果:click promise mutate click promise mutate timeout timeout
inner.click() 触发 inner 的打印后果:click click promise mutate promise timeout timeout

为什么会产生这样的区别?
触发 inner 会有事件冒泡,同时触发 outer 事件,所以会有两次 onclick 事件执行

不同点在于:

  • 页面点击触发,此时执行栈为空,会向宏工作队列增加两个 onclick,执行第一个时产生 promise、mutate,增加到微工作队列,产生 timeout,增加到宏工作队列,也就是第二个 onclick 后边,而后执行栈为空,执行微工作对列,打印 promise、mutate,微工作对列边空,执行宏工作对列,即第二个 onclick,反复以上。
  • js 触发最要害的不同在于他会在最初多一行代码,也就是执行栈是有 script 的,执行 inner.click(),打印 innerclick,增加 promise、mutate 到微工作队列,增加 timeout 到宏工作队列,而后检测执行栈是否为空,发现冒泡触发的 outer.click() 事件,执行栈依然不为空,打印 outerclick,增加 promise 到微工作队列,增加 mutate 时,雷同的一个曾经被增加,所以跳过,后边持续失常执行。
退出移动版