为什么 Javascript 事件处理程序被调用两次?

Why Javascript event handler is called twice?

当我将事件处理程序添加到 class 的元素时,如下所示:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    var divs = document.getElementsByClassName("class1");
    var onclick = function() {
      alert("clicked");
    }
    for (var i = 0; i < divs.length; i++) {
      divs[i].addEventListener("click", onclick);
    }
  </script>
</body>

</html>

如果我单击 div 元素,警告 window 会弹出两次。但是如果我使用下面的代码,警告 window 只会弹出一次。

<html>

<head>
  <title>test</title>
</head>

<body>
  <div class="class1" id="div1">div1</div>
  <script>
    var divs = document.getElementsByClassName("class1");
    var onclick = function() {
      alert("clicked");
    }

    divs.addEventListener("click", onclick);
  </script>
</body>

</html>

下面的代码也会弹出alertwindow两次:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    var div = document.getElementById("div1");
    var onclick = function() {
      alert("clicked");
    }
    div.addEventListener("click", onclick);
  </script>
</body>

</html>

我想知道为什么事件处理程序被调用两次,无论我使用 addEventListener("click",onclick, true); 还是 addEventListener("click",onclick,false);

我用火狐浏览器

发生这种情况是因为您的 onclick 变量是一个全局变量,这意味着当您将函数分配给 onclick:

时,您实际上是在执行此操作
window.onclick = function () {
    alert('click');
};

因此,您将事件侦听器添加到 div window,当您单击 div 时,它在 div 开火一次,在 window.

开火一次

为避免这种情况,请使用 iife 将您的变量屏蔽在全局范围内:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    (function () {
        var divs = document.getElementsByClassName("class1");
        var onclick = function() {
          alert("clicked");
        }
        for (var i = 0; i < divs.length; i++) {
          divs[i].addEventListener("click", onclick);
        }
    })();
  </script>
</body>

</html>

为什么要循环。除了名称(您覆盖本机 onclick)问题之外,为什么不只添加一次?您只有一个 div 具有唯一 ID。

使用匿名函数可以更安全地避免意外使用本机函数名称

const div = document.getElementById("div1");

div.addEventListener("click", () => {
  alert("clicked");
});
<div class="class1" id="div1">div1</div>

如果您有多个元素使用同一个事件处理程序,委托

document.getElementById("container").addEventListener("click", (e) => {
  const div = e.target.closest("div");
  if (div && div.classList.contains("class1")) {
    alert(div.id + " clicked");
  }
});
<div id="container">
  <div class="class1" id="div1">div1</div>
  <div class="class1" id="div2">div2</div>
</div>