题目:实现一个简单的事件总线,支持 on、emit、off、once 方法
知识点Map数据结构以及其属性方法:
const map = new Map()// set —— 添加/更新,返回 map 本身,支持链式
map.set('name', '张三').set('age', 25).set('city', '北京')// get —— 获取值
map.get('name') // '张三'
map.get('age') // 25
map.get('xxx') // undefined// has —— 判断是否存在
map.has('name') // true
map.has('xxx') // false// delete —— 删除,返回 boolean
map.delete('age') // true
map.delete('age') // false(已删除)// clear —— 清空所有
map.clear()
map.size // 0const map = new Map([['a', 1],['b', 2],['c', 3]
])// keys() —— 遍历键
const keysIterator = map.keys()
console.log([...keysIterator]) // ['a', 'b', 'c']// values() —— 遍历值
const valuesIterator = map.values()
console.log([...valuesIterator]) // [1, 2, 3]// entries() —— 遍历键值对(默认迭代器)
const entriesIterator = map.entries()
console.log([...entriesIterator]) // [['a', 1], ['b', 2], ['c', 3]]// Map 的默认迭代器就是 entries()
console.log([...map]) // 等同于 [...map.entries()]// forEach() —— 遍历回调
map.forEach((value, key, mapRef) => {console.log(`${key} → ${value}`)
})
// a → 1
// b → 2
// c → 3// forEach 的第二个参数 thisArg
const handler = {prefix: '🔥',log(key, value) {console.log(`${this.prefix} ${key}: ${value}`)}
}
map.forEach(function(value, key) {this.log(key, value)
}, handler)
// 🔥 a: 1
// 🔥 b: 2
// 🔥 c: 3
实现:
class EventBus {constructor() {this.events = new Map()}on(eventName, callBack) {if (!this.events.has(eventName)) {this.events.set(eventName, [])}this.events.get(eventName).push(callBack)console.log(this.events, 'this.events')return () => this.off(eventName, callBack)}once(eventName, callBack) {const wrapper = (...args) => {callBack(...args)this.off(eventName, wrapper)}// 保留原始回调的引用,用于 off 方法wrapper.originalCallback = callBack;this.on(eventName, wrapper)}emit(eventName, ...args) {if (!this.events.has(eventName)) {return false}try {const callbacks = this.events.get(eventName)callbacks.forEach(call => {call(...args)});} catch {console.log('event execute faild' + eventName)}return true}off(eventName, callBack) {if (!this.events.has(eventName)) {return}let callFuncS = this.events.get(eventName)const index = callFuncS.findIndex(c => c === callBack)if (index > -1) {callFuncS.splice(index, 1)}if (!callFuncS.length) {this.events.delete(eventName)}}
}const eventBus = new EventBus()const onS = eventBus.on('single', (userInfo) => {console.log('single', userInfo)
})
const onS11 = eventBus.on('single', (userInfo) => {console.log('single11', userInfo)
})
eventBus.once('init', () => {console.log('执行一次')
})
eventBus.emit('init')
eventBus.emit('init')eventBus.emit("single", { name: 'hi', age: 10 })onS()
eventBus.emit("single", { name: 'hi', age: 10 }) // 不执行