2013-04-04 55 views
2

我正在製作一款遊戲,我想抽象出我的UI,並根據各種遊戲狀態綁定解綁事件。但我不明白爲什麼這個事件沒有被刪除。看起來範圍在處理程序中是正確的。爲什麼removeeventlistener在此對象上下文中不起作用?

fiddle

相關(精簡)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); 
} 

(...) 

感謝

回答

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

酷!感謝您及時的回覆。我不知道.bind創建一個新的功能。 :) – 2013-04-04 19:01:11

+0

非常有幫助謝謝! – 2015-05-11 17:41:30

+0

爲什麼不呢? - > this.el.addEventListener('click',this.handler.bind(this),true);和this.el.removeEventListener('click',this.handler.bind(this),true); – 2016-02-25 09:40:59

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好的建議,但我認爲一個或兩個以上的函數對內存佔用量沒有任何顯着影響。 – 2013-04-04 19:11:48

+0

謝謝。取決於使用綁定版本的函數最終會有多少對象,但是,這不是在這裏具有主要優勢的內存:-) – 2013-04-04 19:14:34

相關問題