为什么removeeventlistener在此对象上下文中不起作用?

c-c*_*t-p 2 javascript javascript-events

我正在开发一个游戏,我想抽象我的ui,并根据各种游戏状态绑定非绑定事件.但我无法弄清楚为什么这个事件没有被删除.似乎处理程序中的范围是正确的.

小提琴

相关(剥离)js:

var controls = {
    game : {
        el : null,
        cb : null,

        bind : function(el, cb) {
            this.el = el;
            this.cb = cb;
            this.el.addEventListener('click', this.handler.bind(this), true);
        },

        unbind : function() {
            console.log('unbind');
            this.el.removeEventListener('click', this.handler, true);
        },

        handler : function() {
            this.cb();
            this.unbind();
        }
    }
};

var manager = {
    init : function() {
        var c = document.getElementById('c');
        controls.game.bind(c, this.action.bind(this));
    },

    action : function() {
        console.log('c clicked');
    }
};
manager.init();
Run Code Online (Sandbox Code Playgroud)

然而,如果我以这种方式删除事件它的工作原理:

(...)

bind : function(el, cb) {
    this.el = el;
    this.cb = cb;
    var self = this;
    this.el.addEventListener('click', function() {
        self.cb();
        self.el.removeEventListener('click', arguments.callee, true);
    }, true);
}

(...)
Run Code Online (Sandbox Code Playgroud)

谢谢

Fel*_*ing 16

.bind返回一个函数.this.handler.bind(this) !== this.handler!你必须以某种方式存储对新函数的引用.

例如,将引用存储在变量中并使用闭包:

var handler = this.handler.bind(this);
this.el.addEventListener('click', handler, true);

this.unbind = function() {
    this.el.removeEventListener('click', handler, true);
}
Run Code Online (Sandbox Code Playgroud)

作为替代方案arguments.callee,您还可以为该函数指定一个名称:

this.el.addEventListener('click', function handler() {
    self.cb();
    self.el.removeEventListener('click', handler, true);
}, true);
Run Code Online (Sandbox Code Playgroud)


Mis*_*lin 7

而不是玩绑定,这也需要更多的内存,我建议使用以下内容:

var song = {
    handleEvent: function (event) {
      switch (event.type) {
        case: "click":
          console.log(this.name);
          break;
      }
    },
    name: "Yesterday"
};

songNode.addEventListener("click", song);
songNode.click(); // prints "Yesterday" into console
Run Code Online (Sandbox Code Playgroud)

您可以在任何DOM对象上使用obj具有handleEvent属性作为处理程序的对象来捕获其事件,并将事件处理程序的上下文设置为该对象obj而不使用Function.prototype.bind.

这样你也可以删除处理程序,所以

songNode.removeEventListener("click", song);
Run Code Online (Sandbox Code Playgroud)