Prototypes & OOPmedium

Implement an EventEmitter class

Implement a Node.js-style `EventEmitter` with `on`, `off`, `emit`, and `once` methods.

Asked at TikTok, Meta, Airbnb

#classes#observer pattern#events

Answer

class EventEmitter {
  constructor() {
    this._events = {}
  }

  on(event, listener) {
    if (!this._events[event]) this._events[event] = []
    this._events[event].push(listener)
    return this  // for chaining
  }

  off(event, listener) {
    if (!this._events[event]) return this
    this._events[event] = this._events[event]
      .filter(l => l !== listener && l._original !== listener)
    return this
  }

  emit(event, ...args) {
    if (!this._events[event]) return false
    this._events[event].forEach(listener => listener(...args))
    return true
  }

  once(event, listener) {
    const wrapper = (...args) => {
      listener(...args)
      this.off(event, wrapper)
    }
    wrapper._original = listener
    return this.on(event, wrapper)
  }
}

// Usage
const emitter = new EventEmitter()
emitter.on('data', (msg) => console.log('received:', msg))
emitter.once('connect', () => console.log('connected!'))

emitter.emit('connect')  // "connected!"
emitter.emit('connect')  // (nothing — once removed itself)
emitter.emit('data', 'hello')  // "received: hello"

Source: frontendinterviewhandbook.com

Practise more Prototypes & OOP questions →