2013-04-04 101 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