JavaScript 方法中的 addEventListener 和全局函数中的 removeEventListener 时如何调用 removeEventLisener

How to call removeEventLisener when addEventListener in a method and removeEventListener in a global function in JavaScript

有很多关于类似主题的问题和答案,但我觉得这是一个稍微不同的问题,另一个问题的答案并没有完全回答这个问题。我有一个构造函数,它的原型有一个 addEventListener,用全局函数 once 调用。 Once 需要是全局的,但是 addEventListener 需要在原型的方法中。我将如何删除事件侦听器,将 once.bind(that) 放入 removeEventListener 中的函数还是 once

var once = function(event) {
  removeEventListener("keydown", /*something*/);
}
Chomp.prototype.playerMove = function() {
  var that = this;
  addEventListener("keydown", once.bind(that)); 
}

提前致谢! :)

试试这个更新后的代码:

var once = function(event) {
   document.body.removeEventListener("keydown", once);

}

Chomp.prototype.playerMove = function() {
    document.body.addEventListener("keydown", once); 
}

您不能在 once 函数中使用 once.bind(that)That 一次在函数中未知。并且每个带有绑定的事件监听器只能通过与设置方式完全相同的函数调用来删除。如果您在 remove 函数中引用 once.bind(this),它将是与 add 函数中不同的包装器,并且不会删除该事件。上面的代码将 EventListener 附加到 body 并在用户按下键时将其删除。

另一种选择(更好)是将绑定函数保存到播放器上

var once = function(event) {
   document.body.removeEventListener("keydown", this.keyDownEvent);

}

Chomp.prototype.playerMove = function() {
    this.keyDownEvent = once.bind(this);
    document.body.addEventListener("keydown", this.keyDownEvent); 
}

在 "non-strict" 模式下,您可以使用 arguments.callee 获取对函数 once 的引用,由 once.bind(that) 绑定。不幸的是,在 ES5 严格模式下,该功能已被删除。

您可以调用一个单独的函数(必须命名,以便将其传递给 removeEventListener)来处理事件处理程序的解除绑定。

Chomp.prototype.playerMove = function() {
    var that = this;
    var local_once = function() {
        removeEventListener('keydown', local_once);  // deregister this function
        return once.apply(that, arguments);          // invoke global "once"
    }
    addEventListener('keydown', local_once);
}

[太晚了 - 我刚刚意识到这当然需要修改 once,但是没有其他方法可以引用 once.bind(that) 生成的函数,除非它存储在原始 once 可以得到它。此解决方案将 "only call this once" 逻辑保留在 .playerMove].

本地