原文參考: https://www.cxymsg.com/guide/jsWritten.html#%E5%AE%9E%E7%8E%B0event-event-bus
class EventEmitter {
constructor() {
this._event = this._event || new Map() // 儲存事件
this._maxListeners = this._maxListeners || 10 // 設置監(jiān)聽上限
}
}
EventEmitter.prototype.emit = function (type, ...args) {
let handler = null
handler = this._event.get(type)
if (Array.isArray(handler)) {
// 有多個監(jiān)聽者,需要依次觸發(fā)
for (let i = 0; i < handler.length; i++) {
if (args.length > 0) {
handler[i].apply(this, args)
} else {
handler[i].call(this)
}
}
} else if (handler && typeof handler === 'function') {
if (args.length > 0) {
handler.apply(this, args)
} else {
handler.call(this)
}
}
return true
}
EventEmitter.prototype.addListener = function (type, fn) {
let handler = this._event.get(type)
if (!handler) {
this._event.set(type, fn)
} else if (handler && typeof handler === 'function') {
// 如果handler是函數(shù)峰尝,說明目前已經(jīng)存在一個監(jiān)聽者
this._event.set(type, [handler, fn])
} else {
// 已經(jīng)有多個監(jiān)聽者,直接push
handler.push(fn)
}
}
EventEmitter.prototype.removeListener = function (type, fn) {
let handler = this._event.get(type)
if (handler && typeof handler === 'function') {
// 只有一個監(jiān)聽者,直接刪除
this._event.delete(type, fn)
} else if (Array.isArray(handler)) {
// 是數(shù)組购城,說明被監(jiān)聽多次耙蔑,要找到對應的函數(shù)
let position = -1
for(let i = 0; i < handler.length; i++) {
if (handler[i] === fn) {
position = i
}
}
// 如果匹配闭翩,從數(shù)組中移除
if (position !== -1) {
handler.splice(position, 1)
// 移除后臀栈,如果監(jiān)聽只剩一個穴亏,那么取消數(shù)組陷遮,以函數(shù)形式保存
if (handler.length === 1) {
this._event.set(type, handler[0])
}
} else {
return this
}
}
}