Javascript addEventListener如何唯一地标识传递给它的函数?
假设我有如下代码:Javascript addEventListener如何唯一地标识传递给它的函数?,javascript,dom-events,Javascript,Dom Events,假设我有如下代码: let myFunc=()=>{ console.log(“你好”); } 文档。添加的EventListener(“单击”,myFunc); 文档。添加的EventListener(“单击”,myFunc); 文档。添加的EventListener(“单击”,myFunc); 文档。添加的EventListener(“单击”,myFunc)具有特定配置的给定事件侦听器只能添加到元素一次-如果您多次添加它,正如您所看到的,这就像只添加了一个侦听器一样。规范中对此进行了描述:
let myFunc=()=>{
console.log(“你好”);
}
文档。添加的EventListener(“单击”,myFunc);
文档。添加的EventListener(“单击”,myFunc);
文档。添加的EventListener(“单击”,myFunc);
文档。添加的EventListener(“单击”,myFunc)代码>具有特定配置的给定事件侦听器只能添加到元素一次-如果您多次添加它,正如您所看到的,这就像只添加了一个侦听器一样。规范中对此进行了描述:
如果eventTarget的事件侦听器列表不包含类型为侦听器类型的事件侦听器,则回调是侦听器的回调,捕获是侦听器的捕获,然后将侦听器追加到eventTarget的事件侦听器列表
在此基础上,对于被视为重复的侦听器:
谁的类型是侦听器的类型
指事件名称,例如“单击”
回调是侦听器的回调
必须是相同的函数引用(==
添加到先前的侦听器)
捕获是听者的捕获
指侦听器是在捕获阶段还是在冒泡阶段侦听。(这由第三个布尔参数设置为addEventListener
,默认为true
-冒泡,或使用{capture:boolean}
作为第三个参数)
如果上述所有内容与先前添加的侦听器相同,则新的侦听器将被视为重复,并且不会再次添加
如果您愿意,多次添加此类侦听器的一种简单方法是进行内联回调,调用您的侦听器:
let myFunc=()=>{
console.log(“你好”);
}
document.addEventListener(“单击”,()=>myFunc());
document.addEventListener(“单击”,()=>myFunc());
document.addEventListener(“单击”,()=>myFunc());
document.addEventListener(“单击”,()=>myFunc())代码>
单击我
实现在概念上可能是这样的(我忽略了与问题无关的规范细节):
它在侦听器列表中搜索事件类型、与函数和useCapture
参数的现有匹配。如果还没有,它会添加它。是的,我很好奇这是如何实现的。Javascript如何知道已经添加了事件侦听器回调?为了澄清,我不想让函数运行4次,我只想知道它们是如何唯一地标识函数的。请参阅答案中规范的引用。如果eventTarget的事件侦听器列表不包含类型为侦听器类型的事件侦听器,则回调是侦听器的回调,捕获是侦听器的捕获,然后将侦听器追加到eventTarget的事件侦听器列表。如果之前添加了同一个侦听器,那么事件侦听器列表将有这样一个相同的项,因此不会添加新的侦听器。@RyanPeschel函数是对象。您可以将它们与==
进行比较。浏览器在addEventListener
中内部执行此操作,因此它们只有一个函数数组,并且在添加新函数时只需迭代现有函数,以确保尚未添加?有什么办法可以避免这个O(n)的问题吗?我希望避免重复使用现有列表,这就是我最初考虑使用对象的原因。@RyanPeschelMap
也存在,但是W3C关于addEventListener
的规范早在Map
是ECMAScript的一部分之前就存在了。对,这使用了数组。有可能对对象进行O(1)检索吗?有可能,但为什么要麻烦呢?一个元素上的同一事件有多个侦听器是不常见的,而且很少有这么多侦听器,以至于线性搜索会成为性能问题。我预计90%的时间哈希算法会比线性算法更昂贵。是的,我同意。我可能会使用线性,因为它可能更快,也更简单。我只是想知道是否有可能唯一地标识对象中的函数。看起来我需要使用地图或集合。很高兴知道,谢谢@RyanPeschel它还需要检查useCapture
标志。
function addEventListener(type, listener, useCapture = false) {
let typeListeners = this.eventListeners[type];
if (!typeListeners) {
this.eventListeners[type] = [{function: listener, useCapture: useCapture}];
} else {
let found = typeListeners.find(l => l.function === listener && l.useCapture == useCapture);
if (!found) {
typeListeners.push({function: listener, useCapture: useCapture});
}
}
}