3

私はゲームに取り組んでおり、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();

それでも、この方法でイベントを削除すると、次のように機能します。

(...)

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);
}

(...)
4

2 に答える 2

17

.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);
}

の代わりにarguments.callee、関数に名前を付けることもできます。

this.el.addEventListener('click', function handler() {
    self.cb();
    self.el.removeEventListener('click', handler, true);
}, true);
于 2013-04-04T18:47:56.200 に答える
9

より多くのメモリを必要とするバインディングで遊ぶ代わりに、次を使用することをお勧めします。

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

objプロパティを持つオブジェクトを任意の DOM オブジェクトのハンドラーとして使用しhandleEventて、そのイベントをキャッチし、イベント ハンドラーのコンテキストをそのオブジェクトに設定することがobjできますFunction.prototype.bind

そうすれば、ハンドラーを削除することもできるので、

songNode.removeEventListener("click", song);
于 2013-04-04T19:03:42.950 に答える