EventEmitterとかいうライブラリを使っていて、どういう仕組みになっているのか気になったので簡単な物を自分でも調べながら実装してみました。
以下ソースコードと簡単な解説。
function Event(){}
Event.prototype = {
constructor:EventTarget,
addListener:function (type,listener) {
if(!this.hasOwnProperty("_listeners")){
this._listeners = [];
}
if(typeof this._listeners[type] == 'undefined'){
this._listeners[type] = [];
}
this._listeners[type].push(listener);
},
fire:function (event) {
if(!event.target){
event.target = this;
}
if(!event.type){
throw new Error("Event object missing 'type' property.");
}
if(this._listeners && this._listeners[event.type] instanceof Array){
let listeners = this._listeners[event.type];
for(let i=0;i<listeners.length;i++){
listeners[i].call(this,event)
}
}
},
removeListener:function (type,listener) {
if(this._listeners && this._listeners[type] instanceof Array){
let listeners = this._listeners[type];
for(let i=0;i<listeners.length;i++){
if(listeners[i] === listeners){
listeners.splice(i,1);
break;
}
}
}
}
};
やっていることはシンプルで、this._listeners[type]という配列の中に、listener(callback関数)を格納していき、fireでそのcallbackを順番に実行していきます。
一応補足。listeners[i].call(this,event)は、第一引数はlisteners[i]が実行される際に実行される際のthisの値を指定(今回はthisの値をEventオブジェクトのthisにバインドしてる。)、第二引数のeventはlisteners[i]に渡す引数です。