浏览器中物理和编程点击有什么区别

时间:2018-04-28 01:58:11

标签: javascript event-loop

当我研究事件循环时,我遇到了这个问题,我发现这个问题令人困惑。



<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;
&#13;
&#13;

单击内部块时,结果打印如下:

inner click
inner promise 
mutate 
outer click 
outer promise 
mutate 
inner timeout 
outer timeout

然后我添加一些代码

inner.click();
console.log("end");

位于脚本底部并以编程方式触发事件。

&#13;
&#13;
<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;
&#13;
&#13;

我得到了不同的结果,如下:

inner click 
outer click 
end 
inner promise 
mutate 
outer promise 
inner timeout 
outer timeout
  1. 当我进行物理点击时,JavaScript运行时会将点击回调推送到任务队列,同时执行调用堆栈为空。

  2. 当我以编程方式单击时,JavaScript运行时会执行相同的操作,但是 inner.click()位于执行调用堆栈中。

  3. BTW:the explaination in MDN about programmatically click

    那么物理和编程点击浏览器之间有什么区别?似乎inner.click()是同步的。

1 个答案:

答案 0 :(得分:0)

Javascript在单线程模式下运行,这意味着谈论同步与异步有点误导,特别是如果你来自其他语言,如C或Java。 您运行的所有代码总是运行完成,在某种意义上,所有内容都是同步的,因为您只有一个线程来运行js代码(忽略Web工作者更像是一个单独的进程)。
因此,所有I / O处理通常都是通过回调来完成的,以防止阻塞单个线程(除了罕见的已弃用异常,例如alert()函数或同步XHR)。有关更深入的解释see here  我希望它能解决一些困惑。