当我研究事件循环时,我遇到了这个问题,我发现这个问题令人困惑。
<html>
<head>
<style>
#outer {
width: 200px;
height: 200px;
background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
#inner {
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner"></div>
</div>
</body>
<script>
const inner = document.getElementById("inner");
const outer = document.getElementById("outer");
new MutationObserver(() => console.log("mutate")).observe(outer, { attributes: true });
function onClick(e) {
var id = e.currentTarget.id;
console.log(`${id} click`);
setTimeout(() => console.log(`${id} timeout`), 0);
Promise.resolve().then(() => console.log(`${id} promise`));
outer.setAttribute("data-mutation", Math.random());
}
inner.addEventListener("click", onClick);
outer.addEventListener("click", onClick);
</script>
</html>
&#13;
单击内部块时,结果打印如下:
inner click
inner promise
mutate
outer click
outer promise
mutate
inner timeout
outer timeout
然后我添加一些代码
inner.click();
console.log("end");
位于脚本底部并以编程方式触发事件。
<html>
<head>
<style>
#outer {
width: 200px;
height: 200px;
background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
#inner {
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner"></div>
</div>
</body>
<script>
const inner = document.getElementById("inner");
const outer = document.getElementById("outer");
new MutationObserver(() => console.log("mutate")).observe(outer, { attributes: true });
function onClick(e) {
var id = e.currentTarget.id;
console.log(`${id} click`);
setTimeout(() => console.log(`${id} timeout`), 0);
Promise.resolve().then(() => console.log(`${id} promise`));
outer.setAttribute("data-mutation", Math.random());
}
inner.addEventListener("click", onClick);
outer.addEventListener("click", onClick);
inner.click();
console.log("end");
</script>
</html>
&#13;
我得到了不同的结果,如下:
inner click
outer click
end
inner promise
mutate
outer promise
inner timeout
outer timeout
当我进行物理点击时,JavaScript运行时会将点击回调推送到任务队列,同时执行调用堆栈为空。
当我以编程方式单击时,JavaScript运行时会执行相同的操作,但是
inner.click()
位于执行调用堆栈中。
BTW:the explaination in MDN about programmatically click
那么物理和编程点击浏览器之间有什么区别?似乎inner.click()
是同步的。
答案 0 :(得分:0)
Javascript在单线程模式下运行,这意味着谈论同步与异步有点误导,特别是如果你来自其他语言,如C或Java。
您运行的所有代码总是运行完成,在某种意义上,所有内容都是同步的,因为您只有一个线程来运行js代码(忽略Web工作者更像是一个单独的进程)。
因此,所有I / O处理通常都是通过回调来完成的,以防止阻塞单个线程(除了罕见的已弃用异常,例如alert()
函数或同步XHR
)。有关更深入的解释see here
我希望它能解决一些困惑。