来自杰克·阿奇博尔德的博客
小提琴(点击嘿):https://jsfiddle.net/1rpzycLf/
HTML:
<div class="outer">
<div class="inner"></div>
</div>联署材料:
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function() {
console.log('mutate');
}).observe(outer, {
attributes: true
});
// Here's a click listener…
function onClick() {
console.log('click');
setTimeout(function() {
console.log('timeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);在为inner div运行这段代码时,我得到的结果是
click
mutate
click
mutate
promise
promise
timeout
timeout我很想看看是怎么回事。执行应该是
考虑到这一点,我期望日志输出:
click
promise
mutate
click
promise
mutate
timeout
timeout不确定为什么只在处理了两个单击事件处理程序之后才执行promises。理想情况下,第一个承诺应该在第一个mutate之后执行,但我们可以看到,情况显然并非如此。有人知道为什么吗?(使用firefox 54.0)
发布于 2017-07-03 02:44:07
单击元素时,自然会首先输出click,因为它上有一个单击事件处理程序, first 中的单词' click‘的日志将发生在click事件处理程序函数中。
接下来是setTimeout(function() {}, 0);。这会暂停JavaScript的执行,就像C中的线程/进程生成一样,它直到稍后才会执行,所以我们稍后再讨论。
因为您实际上并没有按照承诺做任何事情,所以它立即解决了,注销了第二个。
变异发生在第三次,因为DOM是从上到下读取的,并且在承诺解决后直接突变data-random属性。
最后,既然DOM已被读取完毕,超时将完成第四次。
timeout会从内部<div>记录两次,这是因为单独的执行上下文到调用它的位置。这可以通过一个onclick中的而不是提供与setTimeout(function() {console.log(this)}, 0);相同的上下文来看出。由于鼓泡与延迟的setTimeout一起使用,它尝试首先从子<div>触发,然后从父级 <div> (严格地说是您单击的)触发。
因此,您将得到以下结果:
click
promise
mutate
timeout
timeoutclick、promise和mutate日志总是一个接一个地出现,乘以您同时单击的元素数。timeout日志总是最后一个。
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function() {
console.log('mutate');
}).observe(outer, {
attributes: true
});
// Here's a click listener…
function onClick() {
console.clear(); // Added for clarity
console.log('click');
setTimeout(function() {
console.log('timeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);<div class="outer">Outer
<div class="inner">Inner</div>
</div>
请注意,不同的浏览器处理这些内容的方式不同。由于代码逻辑,我认为假设(我的答案是基于Chrome的)正确处理这个问题。
Firefox在承诺之前处理突变:
click
mutate
promise
promise
timeout
timeoutEdge在承诺之前处理突变和超时:
click
mutate
timeout
promise
timeout
promiseIE根本无法处理承诺,抛出语法错误。
希望这会有帮助!)
https://stackoverflow.com/questions/44876964
复制相似问题