GayCoder,
Увы, но данная реализация вообще не верна и не имеет права на жизнь.
Дело в том что вы в подписке проверяете наличие этой функции в слушателе чего делать категорически нельзя. Допустим у меня есть 2 экземпляра одного класса, и оба подписываются на событие, если метод которым они подписываются лежит в прототипе, то первый подпишется нормально, а второй перетрет его scope (в вашей реализации). Я создал упрощённый макет чтобы продемонстрировать ошибку:
var EventEmiter = {
_handlers: [],
on: function (handler, context) {
if (!this._hasHandler(handler)) {
this._handlers.push({handler: handler, context: context});
}
},
off: function (handler) {
this._handlers.splice(this._handlers.indexOf(handler), 1);
},
emit: function () {
this._handlers.slice().forEach(function (handlerData) {
handlerData.handler.call(handlerData.context);
});
},
_hasHandler: function (handler) {
return this._handlers.some(function (handlerData) {
return handlerData.handler === handler;
});
}
};
var SomeClass = function (name) {
this._name = name;
};
SomeClass.prototype.onEvent = function () {
console.log(this._name);
};
var vasia = new SomeClass('Вася');
var petia = new SomeClass('Петя');
EventEmiter.on(vasia.onEvent, vasia);
EventEmiter.on(petia.onEvent, petia);
EventEmiter.emit();
Как видите отработал только 1 обработчик. В данном случае функция которой они подписываются одна и та же, но она относится к абсолютно разным объектам.
Ну и в методе emit вы почему-то снова не скопировали массив обработчиков перед тем как вызывать события.