点击触发事件和JS触发事件在EventLoop上的区别
varouter=document.querySelector('.outer');varinner=document.querySelector('.inner');newMutationObserver(function(){console.log('mutate');}).observe(outer,{attributes:true})functiononClick(){console.log('click');setTimeout(function(){console.log('timeout')},0);Promise.resolve().then(function(){console.log('promise')});outer.setAttribute('data-random',Math.random());}outer.addEventListener('点击',onClick);inner.addEventListener('click',onClick);//inner.click();对于上面的代码,直接在页面点击trigger会打印出什么样的log序列?如果用js在代码最后触发:inner.click(),那么打印顺序是什么?回答点击outer的打印结果:clickpromisemutatetimeout是正常的eventloop序列,重点关注inner的结果。点击inner的打印结果:clickpromisemutateclickpromisemutatetimeouttimeoutinner.click()触发inner的打印结果:clickclickpromisemutatepromisetimeouttimeout为什么会有这样的区别?触发inner会导致事件冒泡,同时触发outer事件,所以会有两次onclick事件执行。不同的是:页面被点击触发,此时执行栈为空。两次onclicks会被添加到宏任务队列中,第一个会被执行。Promise和mutate产生,加入microtask队列,产生timeout,加入macrotask队列,也就是在第二次onclick后面,然后执行栈为空,执行microtask,promise,mutate,microtask被打印边为空,执行宏任务栏,即第二次onclick,重复上面。jstrigger最关键的区别在于它最后会多一行代码,即执行栈有一个脚本,执行inner.click(),打印innerclick,添加promise和mutate到microtask队列,并在macrotaskQueue中加入timeout,然后检查执行栈是否为空,发现冒泡触发的outer.click()事件,执行栈仍然不为空,打印outerclick,在microtask队列中加入promise,添加mutate的时候,同样的已经添加了,所以略过,后面继续正常执行。