我在应用程序内部使用EventEmitter2作为消息总线。现在我需要绑定和取消绑定一些事件处理程序。由于我还希望将它们绑定到给定的上下文,因此我使用了以下语法:
messageBus.on('foo::bar', _.bind(eventHandler, this));
问题是我需要在稍后的时间点解除绑定,所以我写:
messageBus.off('foo::bar', _.bind(eventHandler, this));
不幸的是,这不起作用,因为_.bind
每次都返回一个包装器函数的新实例。当然,现在我可以运行一次_.bind
并绑定包装的函数,例如:
var fn = _.bind(eventHandler, this);
messageBus.on('foo::bar', fn);
messageBus.off('foo::bar', fn);
这工作得很好,但是如果你有几个事件处理程序,代码很快就会变得不那么可读。
如何在不需要外部化bind
函数调用的情况下解决这个问题?是否有一个替代函数,总是返回相同的包装器,如果你调用它多次和函数以及上下文是相同的?
Underscore.js为这个用例提供了一个bindAll
方法,来自文档:
在对象上绑定一些方法,由methodNames指定,当调用这些方法时将在该对象的上下文中运行
如果做不到这一点,你可以使用一个闭包,它在调用时总是返回相同的绑定函数,即:
function getOrCreateBoundEventHandlerFor(eventType, callback) {
// Initialise the handler map if it's not already been created.
this._boundEventHandlerMap = this._boundEventHandlerMap || {};
// If no handler was mapped, create a new one.
if (this._boundEventHandlerMap[eventType] === void 0) {
this._boundEventHandlerMap[eventType] = _.bind(callback, this);
}
return this._boundEventHandlerMap[eventType];
}