SOURCE

class EventEmitter {
  /* TODO */
  listeners = {}
  on(name, fn) {
    if (this.listeners.hasOwnProperty(name)) {
      this.listeners[name][fn.name] = fn;
    }else{
      this.listeners[name]={}
      this.listeners[name][fn.name] = fn;
    }
  }
  emit(name) {
    const args = [].slice.call(arguments, 1);
    if (this.listeners.hasOwnProperty(name)) {
      for (let key in this.listeners[name]) {
        if (this.listeners[name].hasOwnProperty(key)) {
          this.listeners[name][key].apply(null,args);
        }
      }
    }
  }
  off(name, fn) {
    if (this.listeners.hasOwnProperty(name) && this.listeners[name].hasOwnProperty(fn.name)) {
      delete this.listeners[name][fn.name]
    }
  }
}
const emitter = new EventEmitter()
const sayHi = (name) => console.log(`Hello ${name}`)
const sayHi2 = (name) => console.log(`Good night, ${name}`)

emitter.on('hi', sayHi)
emitter.on('hi', sayHi2)
emitter.emit('hi', 'ScriptOJ')
// => Hello ScriptOJ
// => Good night, ScriptOJ

emitter.off('hi', sayHi)
emitter.emit('hi', 'ScriptOJ')
// => Good night, ScriptOJ

const emitter2 = new EventEmitter()
emitter2.on('hi', (name, age) => {
  console.log(`I am ${name}, and I am ${age} years old`)
})
emitter2.emit('hi', 'Jerry', 12)
// => I am Jerry, and I am 12 years old
console 命令行工具 X clear

                    
>
console