最佳性能方式编写自定义的 .on()/.bind() JavaScript函数

3

我经常编写一些小型的库和模块,通常这些库和模块都与一些事件相关联。 目前为止,我的编写方式通常是以下方式(大大简化):

Library.prototype.on = function(event, callback){
  self = this;
  self.events[event] = callback;
}

那么用户可能会执行以下操作:

Library.on('foo',function(){
  console.log('bar');
});

有更好的、性能更高的方法来实现这个吗?还是这是一种标准的实现方式?我想要一个简单的API,可以将其放入任何JS项目中以支持此行为。

2个回答

2
var EventEmitter = {
    constructor: function _constructor() {
        this._events = [];
        return this;
    },
    on: function _on(ev, handler) {
        if (!this._events[ev]) {
            this._events[ev] = [];
        }
        this._events[ev].push(handler);
    },
    removeListener: function _removeListener(ev, handler) {
        if (!this._events[ev]) return;
        this._events[ev].splice(this._events[ev].indexOf(handler), 1);
    },
    removeAll: function _removeAll(ev) {
        delete this._events[ev];
    },
    emit: function _emit(ev, data) {
        if (!this._events[ev]) return;
        this._events[ev].forEach(invokeHandler);

        function invokeHandler(handler) {
            handler(data);
        }
    }
};

当我需要快速、简单地自定义事件时,我使用一个小的EventEmitter

我的实现与你的唯一区别在于,我的允许每个事件有多个回调函数。

对于任何重要的事情,我会使用像EventEmitter2这样的事件库。


唯一奇怪的事情是removeListener只删除了最后添加的。我想removeListener('event')的预期用法可能类似于jQuery中使用unbind('event'),它会删除所有引用(除非你添加一个像event.foo这样的命名空间)。 - Oscar Godson
@OscarGodson 你必须手动删除所有的监听器。调用 removeListener(ev) 只会因为巧合而删除最后一个监听器(索引为-1,因此它会删除最后一个项目)。你应该调用 removeListener(ev, handler) - Raynos
我添加了一个“全部删除”选项,以便更轻松地进行拆卸,只需将this._events[ev] = []设置为空数组即可。 - Oscar Godson

0
你正在寻找 JavaScript 的观察者模式SpineBackbone 有一些不错的观察者实现。
但一个新的好模式是 Promise 模式,它在CommonJS中有记录文档。 jQuery 1.7已经实现并深度使用 Promise 模式。
我最喜欢的 Promise 模式实现是 @kriskowal 的Q
我希望这些资源能帮助你在你的探索中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接