1. class EventEmitter {
    2. constructor() {
    3. // handlers是一个map,用于存储事件与回调之间的对应关系
    4. this.handlers = {}
    5. }
    6. // on方法用于安装事件监听器,它接受目标事件名和回调函数作为参数
    7. on(eventName, cb) {
    8. // 先检查一下目标事件名有没有对应的监听函数队列
    9. if (!this.handlers[eventName]) {
    10. // 如果没有,那么首先初始化一个监听函数队列
    11. this.handlers[eventName] = []
    12. }
    13. // 把回调函数推入目标事件的监听函数队列里去
    14. this.handlers[eventName].push(cb)
    15. }
    16. // emit方法用于触发目标事件,它接受事件名和监听函数入参作为参数
    17. emit(eventName, ...args) {
    18. // 检查目标事件是否有监听函数队列
    19. if (this.handlers[eventName]) {
    20. // 这里需要对 this.handlers[eventName] 做一次浅拷贝,主要目的是为了避免通过 once 安装的监听器在移除的过程中出现顺序问题
    21. const handlers = this.handlers[eventName].slice()
    22. // 如果有,则逐个调用队列里的回调函数
    23. handlers.forEach((callback) => {
    24. callback(...args)
    25. })
    26. }
    27. }
    28. // 移除某个事件回调队列里的指定回调函数
    29. off(eventName, cb) {
    30. const callbacks = this.handlers[eventName]
    31. const index = callbacks.indexOf(cb)
    32. if (index !== -1) {
    33. callbacks.splice(index, 1)
    34. }
    35. }
    36. // 为事件注册单次监听器
    37. once(eventName, cb) {
    38. // 对回调函数进行包装,使其执行完毕自动被移除
    39. const wrapper = (...args) => {
    40. cb(...args)
    41. this.off(eventName, wrapper)
    42. }
    43. this.on(eventName, wrapper)
    44. }
    45. }