map管理事件监听器以事件类型为键、回调数组为值,支持快速注册/查找/批量移除;可通过字符串拼接或嵌套map处理options差异,结合去重与once机制,并封装on/off方法桥接原生事件系统。

用 Map 管理事件监听器,核心在于以事件类型为键、监听函数集合为值,实现快速注册、查找与批量移除。它不解决内存泄漏问题(那是 WeakMap 的专长),但能显著提升监听器的组织效率和运行时性能。
结构设计:Map 存监听器列表
每个事件类型(如 "click"、"resize")作为 Map 的 key;对应 value 是一个数组,存放所有绑定到该类型的回调函数。
- 添加监听器时,先查 Map 中是否存在该 type 的数组,没有就新建并 set 进去,再 push 回调
- 触发事件时,直接 get(type) 拿到数组,遍历执行,无需遍历全部监听器
- 移除指定监听器时,通过 findIndex + splice 定位并删除;清空某类事件,直接 delete(key)
支持选项区分:复合 key 或嵌套 Map
同一事件类型可能因 options(如 {once: true, capture: false})需要独立管理。可选两种方式:
- 拼接字符串 key:
`${type}|${JSON.stringify(options)}`,简单直接,适合 options 结构稳定 - 二级 Map:
Map<string map function>></string>,外层是 type,内层用 options 字符串作 key,更易维护且避免 JSON 序列化开销
防止重复绑定与 once 支持
重复绑定同一函数会导致多次执行,需主动去重;而 once 要求执行后自动清理。
- 注册前检查数组中是否已存在该 handler 引用(=== 判断)
- 在事件触发逻辑中,对带有 once 标记的 handler 执行后立即从数组中移除
- 可将 handler 封装为带元数据的对象:
{ fn, once, options },便于统一管理
兼容原生事件系统(如 addEventListener)
Map 管理的是逻辑监听器,不替代浏览器底层机制。实际绑定仍调用原生方法,但由 Map 控制生命周期:
- 封装
on(el, type, handler, options):内部调用 addEventListener,并把 handler 记入 Map - 封装
off(el, type, handler):调用 removeEventListener,并同步从 Map 删除 - 页面卸载或组件销毁时,遍历 Map 清理所有关联的原生监听器,避免残留











