js中两个相同监听器的捕获和冒泡的执行顺序

The executing order of capture and bubble for two same listeners in js

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>capture and bubble</title>
  <style type="text/css">
  #child{
    background: red;
    width:50px;
    height:50px;
  }
  #father{
    width:100px;
    height:100px;
    background:green;
  }
  </style>
</head>
<body>
    <div id='father'>
      <div id='child'></div>
    </div>
</body>
<script type="text/javascript">
  var parent = document.getElementById("father");
  var child = document.getElementById('child');
  var html = document.getElementsByTagName("html")[0];
  var body = document.body;
  parent.addEventListener("click",function() {
    console.log("I am capturing parent");
  },true);
   parent.addEventListener("click",function() {
    console.log("I am parent");
  },false);
   child.addEventListener("click",function() {
    console.log("I am capturing child");
  },true);
  child.addEventListener("click",function() {
    console.log("I am child");
  },false);
  body.addEventListener("click",function() {
    console.log("I am capturing body");
  },true);  
  body.addEventListener("click",function() {
    console.log("I am body");
  },false);
  html.addEventListener("click",function() {
    console.log("I am capturing html");
  },true);
  html.addEventListener("click",function() {
    console.log("I am html");
  },false);
  parent.addEventListener("click",function() {
    console.log("I am capturing parent");
  },true);
   parent.addEventListener("click",function() {
    console.log("I am parent");
  },false);
</script>
</html>

为了上面的html包含一个js显示capture和bubble的执行顺序,我为parent(div父绑定了两次capture和bubble的监听器),parent(div father)的一对capture和bubble在js脚本部分从第5行到第10行; parent(div 父亲)的另一对捕获和气泡在 js 脚本部分的末尾。

点击绿色的div(父亲div),在控制台得到结果

test.html:50 I am capturing html
test.html:44 I am capturing body
test.html:32 I am capturing parent
test.html:35 I am parent
test.html:56 I am capturing parent
test.html:59 I am parent
test.html:47 I am body
test.html:53 I am html

为什么结果不是下面的?

test.html:50 I am capturing html
test.html:44 I am capturing body
test.html:32 I am capturing parent
test.html:56 I am capturing parent
test.html:35 I am parent
test.html:59 I am parent
test.html:47 I am body
test.html:53 I am html

请详细说明。

MDN documentation for addEventListener 状态:

Note: For event listeners attached to the event target, the event is in the target phase, rather than the capturing and bubbling phases. Events in the target phase will trigger all listeners on an element in the order they were registered, regardless of the useCapture parameter.

这就是这里发生的事情。事件侦听器附加到事件目标(在您的示例中为 parent),因此事件处于目标阶段并且侦听器按照它们注册的顺序被触发。

请注意,如果您单击 child,则不会发生这种情况,因为事件处于捕获或冒泡阶段。预期的结果是:

I am capturing html
I am capturing body
I am capturing parent
I am capturing parent
I am capturing child
I am child
I am parent
I am parent
I am body
I am html

事件流有很好的解释和图表here

最重要的是目标阶段触发捕获和冒泡动作。

other material with very understandable language states here

第二阶段(“目标阶段”:事件到达元素)没有单独处理: 捕获和冒泡阶段的处理程序在该阶段触发。

刚注意到 MDN 更新了 addEventListener 的状态:

Note: For event listeners attached to the event target, the event is in the target phase, rather than the capturing and bubbling phases. Event listeners in the capturing phase are called before event listeners in any non-capturing phases.

这意味着结果与您的预期完全相同

I am capturing html
I am capturing body
I am capturing parent
I am capturing parent
I am capturing child
I am child
I am parent
I am parent
I am body
I am html

console in chrome