Javascript Can';t删除eventListener,已尝试6小时

Javascript Can';t删除eventListener,已尝试6小时,javascript,removeeventlistener,Javascript,Removeeventlistener,我已经尝试了几个小时删除事件侦听器,但没有成功 由于我进行了一次测试,我明白问题可能在于侦听器引用 这是代码。为了清晰起见,我把一切都简化了 const COMPLETE = 'complete'; let dispatcher = new EventTarget; class Template { complete(e){ e.currentTarget.removeEventListener(COMPLETE, this.co

我已经尝试了几个小时删除事件侦听器,但没有成功

由于我进行了一次测试,我明白问题可能在于侦听器引用

这是代码。为了清晰起见,我把一切都简化了

    const COMPLETE = 'complete';
    let dispatcher = new EventTarget;

    class Template {
        complete(e){
            e.currentTarget.removeEventListener(COMPLETE, this.complete);
            console.log('I run only once');
        }
    }

    let child = new Template();
    child.exe = function(){
        dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
    }
    child.exe();


    
    dispatcher.dispatchEvent(new Event(COMPLETE));
    dispatcher.dispatchEvent(new Event(COMPLETE));
    dispatcher.dispatchEvent(new Event(COMPLETE));
当然,在控制台中,您可以阅读三遍“我只运行一次”

我所做的测试涉及到额外的变量“functionReference”,我在其中存储侦听器引用。然后它就起作用了

    let functionReference
    const COMPLETE = 'complete';

    let dispatcher = new EventTarget;

    class Template {
        complete(e){
            e.currentTarget.removeEventListener(COMPLETE, functionReference);
            console.log('i run only once');
        }
    }

    let child = new Template();
    child.exe = function(){
        functionReference = this.complete.bind(this);
        dispatcher.addEventListener(COMPLETE, functionReference);
    }
    child.exe();


    
    dispatcher.dispatchEvent(new Event(COMPLETE));
    dispatcher.dispatchEvent(new Event(COMPLETE));
    dispatcher.dispatchEvent(new Event(COMPLETE));
现在在控制台中只有一次“我只运行一次”

发生了什么事?为什么我不能删除那个侦听器

*****下面的更新/解决方案 ***非常感谢蒂姆和阿姆伦德辛格


谢谢你的解释! 感谢天目的伟大创意和解决方案! 非常感谢您的快速帮助!我已经好几年没这么困了

以下是Teemu解决方案:

const COMPLETE = 'complete';
let dispatcher = new EventTarget;

class Template {
    constructor(){
        this.complete = (e)=>{
            e.currentTarget.removeEventListener(COMPLETE, this.complete);
            console.log('i run only once');
        }
    }
}

let child = new Template();
child.exe = function(){
    dispatcher.addEventListener(COMPLETE, this.complete);
}
child.exe();



dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
或者,可以存储对侦听器的引用,并将其作为变量传递。

来自MDN:

bind()方法创建一个新函数,该函数在调用时具有 此关键字设置为提供的值,并具有给定的 调用新函数时,将在任何函数前面提供参数

在第一个示例中:

dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
绑定创建一个新函数并将其作为处理程序附加。这就是为什么您无法删除事件侦听器,因为您以前使用bind附加的事件侦听器与您的完整方法不同

在第二个示例中:

functionReference = this.complete.bind(this);
dispatcher.addEventListener(COMPLETE, functionReference);
您正在将bind返回的新函数注册为侦听器,然后将其删除,因为在这两个add/remove中,侦听器是相同的,这就是它被删除的原因