2013-04-04 3 views
2

Я работаю над игрой, и я хотел бы абстрагировать свой ui и связывать события развязывания на основе различных состояний игры. Но я не могу понять, почему это событие не удаляется. Кажется, что область действия правильна в обработчике.Почему removeeventlistener не работает в этом объектном контексте?

fiddle

соответствующих (усеченные) ЯШ:

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

(...) 

благодаря

ответ

15

.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); 
+0

Круто! Спасибо за быстрый ответ. Я не знал о создании новой функции. :) –

+0

Очень полезно спасибо! –

+0

почему бы и нет? -> this.el.addEventListener ('click', this.handler.bind (this), true); и this.el.removeEventListener ('click', this.handler.bind (this), true); –

7

Вместо того, чтобы играть с связывание, которое также требует большего объема памяти, я бы рекомендовал использовать the following:

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, который имеет свойство handleEvent как обработчик на любом объекте DOM, чтобы поймать его события и задать контекст обработчика события obj без использования Function.prototype.bind.

Таким образом, вы также можете удалить обработчик, так

songNode.removeEventListener("click", song); 
+0

+1 хорошее предложение, хотя я не думаю, что одна или две другие функции оказывают существенное влияние на объем памяти. –

+0

Спасибо. Зависит от того, сколько объектов закончит использование связанных функций функции, но да, это не главное, главное преимущество здесь :-) –

Смежные вопросы