简易实现 EventEmitter

106 阅读1分钟
class EventEmitter {
  #event = Object.create(null)

  on(type, listener) {
    // 如果当前事件还没有被监听过, 则为该事件赋一个数组
    this.#event[type] = this.#event[type] ?? []
    
    // 为该事件添加监听函数
    this.#event[type].push(listener)
    
    // 返回 EventEmitter 实例对象以供链式调用
    return this
  }

  emit(type, ...args) {
    // 如果没有事件所对应的监听函数数组, 则返回 false 表示事件触发失败
    if (this.#event[type] == undefined) return false
    
    // 调用事件所对应的所有监听函数并将监听函数的 this 指向 EventEmitter 实例对象
    this.#event[type].forEach(fn => {
      Reflect.apply(fn, this, args)
    })
    
    // 返回 true 表示事件触发成功
    return true
  }

  once(type, listener) {
    // 包装函数以使该监听函数触发一次即删除
    const onceFn = (...args) => {
      listener(...args)
      this.off(type, onceFn)
    }
    // 防止在调用 emit 之前调用 off 取消该监听函数失败
    onceFn.origin = listener
    
    // 返回 EventEmitter 实例对象以便链式调用
    return this.on(type, onceFn)
  }

  off(type, listener) {
    if (this.#event[type] == undefined) return this

    // 删除事件对应的监听函数数组中符合条件的监听函数
    this.#event[type] = this.#event[type].filter(fn => {
      return fn !== listener && fn.origin !== listener
    })
    
    // 如果事件对应的监听函数数组中没有监听函数, 则删除该事件对应的数组
    if (this.#event[type].length === 0) 
      delete this.#event[type]
    
    return this
  }

  removeAllListeners(type) {
    // 如果没有传入事件, 则删除所有的事件所对应的全部监听函数
    if (type) delete this.#event[type]
    else this.#event = Object.create(null)
    
    return this
  }

  listeners(type) {
    return this.#event[type]
  }
}