Javascript 创建可以添加、触发和取消订阅事件的事件触发类

Javascript 创建可以添加、触发和取消订阅事件的事件触发类,javascript,Javascript,我正在处理这个事件发射器javascript问题,有人能帮助我理解如何在不向其传递任何参数的情况下实现release() 下面的代码应该能够根据类型将事件添加到数组中。通过调用sub.release(),在接受任意数量的参数时按类型触发事件,并使用引用释放(取消订阅)事件 这就是我迄今为止所实施的,我感谢任何反馈: 类发射器{ 构造函数(){ this.events={}; } 订阅=(类型,fn)=>{ if(this.events[type]==未定义){ 此.events[type]=[

我正在处理这个事件发射器javascript问题,有人能帮助我理解如何在不向其传递任何参数的情况下实现release()

下面的代码应该能够根据类型将事件添加到数组中。通过调用
sub.release()
,在接受任意数量的参数时按类型触发事件,并使用引用释放(取消订阅)事件

这就是我迄今为止所实施的,我感谢任何反馈:

类发射器{
构造函数(){
this.events={};
}
订阅=(类型,fn)=>{
if(this.events[type]==未定义){
此.events[type]=[];
}
this.events[type].push(fn);
归还这个;
}
emit=(类型,…参数)=>{
for(设i=0;i{
}
}

release
方法不应该是
Emitter
类的实例方法,
subscribe
方法不应该返回
Emitter
实例。对
subscribe
的每次调用都应返回具有
release
方法的不同对象

在JS中,只需创建一个简单的对象返回这里就可以了,但如果需要,还可以创建一个单独的
订阅
类。下面是一个简单对象的示例

此外,我将其切换为对事件使用
,因为它使事情变得更简单

class Emitter {
    constructor() {
        this.events = {};
    }
    
    subscribe = (type, fn) => {
        if(this.events[type] === undefined) {
            this.events[type] = new Set();
        }
        
        this.events[type].add(fn);
        
        return {
            release: () => {
                this.events[type].delete(fn);
            }
        };
    }
    
    emit = (type,...args) => {
        if (this.events[type] === undefined) {
            return;
        }
        [...this.events[type]].forEach(sub => sub(...args));
    }
    
}

谢谢你的回复@Chris Rollins,真的很有帮助。你能解释一下为什么在这里使用集合会让事情变得更容易吗?在决定一个集合或不同的数据结构是否更好时,需要考虑哪些因素?当从
集合中删除某些内容时,可以说,您不必担心会造成“漏洞”。如果您使用的是数组,删除某个项会在该位置留下未定义的
,因此您需要移动其他项以填充该数组,或者在搜索时检查这些孔。无论哪种方式,都会有更多的代码需要编写,这很烦人,也会有更多的机会出现bug。此外,在这种情况下,我并不太担心性能差异,因为我不认为您会将其扩展到大量订阅,但实际上
的性能应该更好,这是一个不错的奖励。至于性能,
Set
Map
在需要搜索特定项目或需要从任意位置删除内容时效果更好。如果它们是有序的,则通常实现为某种树;如果它们是无序的,则实现为哈希表。在这两种情况下,您都可以插入和删除,而无需移动其他项目。当您不必搜索时(总是知道您需要的索引),数组是最好的。这里的另一个考虑因素是是否允许同一函数引用注册多次。在
集合中
每个值都是唯一的,因此不能多次添加同一引用。请注意,您可以添加相同的函数,因为它是引用类型。似乎您不会故意多次添加相同的函数,因此这可能是一个好处,但我认为这可能是有争议的。无论如何,当您考虑使用
Set
时,这种唯一性是主要考虑因素之一。在某些情况下,这可能是一个巨大的好处,但在其他情况下,它可能不是。
class Emitter {
    constructor() {
        this.events = {};
    }
    
    subscribe = (type, fn) => {
        if(this.events[type] === undefined) {
            this.events[type] = new Set();
        }
        
        this.events[type].add(fn);
        
        return {
            release: () => {
                this.events[type].delete(fn);
            }
        };
    }
    
    emit = (type,...args) => {
        if (this.events[type] === undefined) {
            return;
        }
        [...this.events[type]].forEach(sub => sub(...args));
    }
    
}