Open ForeveHG opened 4 years ago
草率而且很有问题版:
var Event = {
listeners: {},
// 通过on接口监听事件eventName
// 如果事件eventName被触发,则执行callback回调函数
on: function (eventName, callback) {
if (!this.listeners[eventName]) this.listeners[eventName] = [];
this.listeners[eventName].push(callback)
},
// 触发事件 eventName
emit: function (eventName) {
if (this.listeners[eventName]) {
this.listeners[eventName].forEach(callback => {
callback(...[].slice.call(arguments, 1))
})
}
}
};
测试代码中复用Event是使用Object.assign方法,这个方法只能浅复制,新的对象中不光会有on,emit还会有用来存放回调函数的listeners属性,并且listeners属性被公用了,会导致 person1.emit('call2'); person2.emit('call1'); 这两个本来不该有输出的调用输出内容
分析一下,listeners是不应该被拷贝的,每个复用Event的对象自身都应该持有一个listeners,而Object.assign是只拷贝对象自身的可枚举属性,根据这几点,可以写出下面这一版:
var Event = {
// 通过on接口监听事件eventName
// 如果事件eventName被触发,则执行callback回调函数
on: function (eventName, callback) {
if (!this._listeners) Object.defineProperty(this, '_listeners', {
writable: true,
value: {}
})
if (!this._listeners[eventName]) this._listeners[eventName] = [];
this._listeners[eventName].push(callback)
},
// 触发事件 eventName
emit: function (eventName) {
if (this._listeners[eventName]) {
this._listeners[eventName].forEach(callback => {
callback(...[].slice.call(arguments, 1))
})
}
}
};
请实现下面的自定义事件 Event 对象的接口,功能见注释(测试1) 该 Event 对象的接口需要能被其他对象拓展复用(测试2)