首页 > 解决方案 > How does addEventListener uniquely identify the functions passed to it?

问题描述

Say I have some code like this:

let myFunc = () => {
    console.log("hello");
}
 
document.addEventListener("click", myFunc);
document.addEventListener("click", myFunc);
document.addEventListener("click", myFunc);
document.addEventListener("click", myFunc);

Why does clicking the document only console log once? I don't mind this behavior, but I'm just curious how it is implemented.

For example, if you did something like this:

let events = {};

function addEventListener(key, callback) {
  if (!key) { return; }

  if (!events.hasOwnProperty(key)) {
    events[key] = {};
  }

  events[key][callback] = callback;
}

Then you're using a function as a key, but aren't only strings valid for keys? How does JavaScript uniquely identify the functions so that it knows not to add the same one multiple times?

标签: javascriptdom-events

解决方案


具有特定配置的给定事件侦听器只能添加到元素一次- 如果您多次添加它,如您所见,就好像只添加了一个侦听器。这在此处的规范中有所描述:

  1. 如果 eventTarget 的事件监听列表中不包含类型为监听器类型的事件监听器,callback 为监听器回调,capture 为监听器捕获,则将监听器追加到 eventTarget 的事件监听器列表中。

为了扩展这一点,让听众被认为是这样的重复:

其类型是侦听器的类型

指事件名称,例如'click'

callback 是监听器的回调

必须是相同的函数引用(===添加到先前的侦听器)

capture 是监听器的捕获

指的是监听器是在捕获阶段还是冒泡阶段监听。(这由第三个布尔参数设置为addEventListener,默认为true- 冒泡,或{ capture: boolean }作为第三个参数)

如果以上都与之前添加的监听器相同,那么新的监听器将被视为重复,不会再次添加。


如果您愿意,可以多次添加此类侦听器的一种简单方法是创建一个调用您的侦听器的内联回调:

let myFunc = () => {
    console.log("hello");
}
 
document.addEventListener("click", () => myFunc());
document.addEventListener("click", () => myFunc());
document.addEventListener("click", () => myFunc());
document.addEventListener("click", () => myFunc());
click me

以上将起作用,因为传递给的回调addEventListener不相等:() => myFunc()is not ===to () => myFunc()


推荐阅读