Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript addEventListener如何唯一地标识传递给它的函数?_Javascript_Dom Events - Fatal编程技术网

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)的问题吗?我希望避免重复使用现有列表,这就是我最初考虑使用对象的原因。@RyanPeschel
    Map
    也存在,但是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});
            }
        }
    }