点击触发事件和JS触发事件在EventLoop上的区别
问题
话不多说,直接上代码分析:
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
事件执行【点击触发事件和JS触发事件在EventLoop上的区别】不同点在于:
- 页面点击触发,此时执行栈为空,会向宏任务队列添加两个
onclick
,执行第一个时产生promise、mutate
,添加到微任务队列,产生timeout
,添加到宏任务队列,也就是第二个onclick
后边,然后执行栈为空,执行微任务对列,打印promise、mutate
,微任务对列边空,执行宏任务对列,即第二个onclick
,重复以上。 js
触发最关键的不同在于他会在最后多一行代码,也就是执行栈是有script
的,执行inner.click()
,打印inner
的click
,添加promise、mutate
到微任务队列,添加timeout
到宏任务队列,然后检测执行栈是否为空,发现冒泡触发的outer.click()
事件,执行栈仍然不为空,打印outer
的click
,添加promise
到微任务队列,添加mutate
时,相同的一个已经被添加,所以跳过,后边继续正常执行。
推荐阅读
- 事件代理
- 事件处理程序
- Android事件传递源码分析
- 66万奔驰漏油事件看宝宝无理取闹
- 「我的2017」——2017|「我的2017」——2017,大事件盘点
- android防止连续点击的简单实现(kotlin)
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- 心理工作要不断的评估现实事件对来访者心理造成的影响是什么
- 如何做2020年年度复盘,写出100件成就事件
- 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件