const observers = []
 
export default Object.freeze({
  notify: (data) => observers.forEach((observer) => observer(data)),
  subscribe: (func) => observers.push(func),
  unsubscribe: (func) => {
    ;[...observers].forEach((observer, index) => {
      if (observer === func) {
        observers.splice(index, 1)
      }
    })
  },
})

Tradeoffs

Separation of Concerns

The observer objects aren’t tightly coupled to the observable object, and can be (de)coupled at any time. The observable object is responsible for monitoring the events, while the observers simply handle the received data.

Decreased performance

Notifying all subscribers might take a significant amount of time if the observer handling becomes too complex, or if there are too many subscibers to notify.

References

Object Freeze
https://javascriptpatterns.vercel.app/patterns/design-patterns/observer-pattern