EventEmitter 实现原理

661 阅读1分钟

EventEmitter 实现原理

EventEmitter 为事件监听器(实质为一个发布订阅模式),其实现要素如下:

  • on(eventName, fn) 用于注册事件监听器
  • once(eventName, fn) 用于注册事件监听器,且只触发一次
  • emit(eventName, ...args) 用于触发对应事件
  • off(eventName, [fn]) 用于注销事件监听器,如第二个参数为空,则注销该事件下所有的事件监听器
// EventEmmiter 简易实现
class EventEmitter {
  constructor() {
    this.events = Object.create(null)
  }

  // 监听事件
  on(eventName, fn) {
    if (!this.events[eventName]) {
      this.events[eventName] = []
    }

    this.events[eventName].push(fn)
  }

  // 触发事件
  emit(eventName, ...args) {
    if (!this.events[eventName] || !Array.isArray(this.events[eventName])) return

    this.events[eventName].map(fn => {
      fn.apply(this, args)
    })
  }

  // 注销事件
  off(eventName, fn) {
    if (fn === void 0) {
      this.events[eventName] = null
      return
    }

    if (this.events[eventName].length) {
      const index = this.events[eventName].findIndex(item => item === fn)

      if (index > -1) {
        this.events[eventName].splice(index, 1)
      }
    }
  }

  // 注册单次执行的事件
  once(eventName, fn) {
    const only = (...args) => {
      fn.apply(this, args)
      this.off(eventName)
    }

    this.on(eventName, only)
  }
}
// test on/emit function
const eventBus = new EventEmitter()
eventBus.on('click', () => console.log(1))
eventBus.emit('click')
// --- output ---
// 1

// test on/emit function
const cb = function (...args) {
  console.log('2: ', args)
}
eventBus.on('input', () => console.log(1))
eventBus.on('input', cb)
eventBus.emit('input', {name: 'jack'}, {age: 18})
// --- output ---
// 1
// 2:  [ { name: 'jack' }, { age: 18 } ] 

// test on/off/emit function
eventBus.off('input', cb)
eventBus.emit('input', {name: 'jack'}, {age: 18})
// --- output ---
// 1

// test on/off/emit function
eventBus.off('input')
eventBus.emit('input', {name: 'jack'}, {age: 18})
// --- output ---

// test once/emit function
eventBus.once('change', cb)
eventBus.emit('change', {name: 'jack'})
eventBus.emit('change', {name: 'jack'})
// --- output ---
// [ { name: 'jack' } ]