Javascript 为什么这个简单的基于阵列的事件发射器顺序敏感?

Javascript 为什么这个简单的基于阵列的事件发射器顺序敏感?,javascript,arrays,push,eventemitter,Javascript,Arrays,Push,Eventemitter,如果事件处理程序前面有“.once”事件处理程序,则简单事件发射器不会激发该事件处理程序。我无法理解为什么会发生这种情况 const发射器=(主机={},侦听器={})=>Object.assign(主机{ 发射(事件、数据){ (侦听器[事件]| |[]).forEach(h=>h(数据)) }, 打开(事件、处理程序){ 如果(!侦听器[event])侦听器[event]=[] 侦听器[事件]。推送(处理程序) return()=>host.off(事件、处理程序) }, 一次(事件、处理

如果事件处理程序前面有“.once”事件处理程序,则简单事件发射器不会激发该事件处理程序。我无法理解为什么会发生这种情况

const发射器=(主机={},侦听器={})=>Object.assign(主机{
发射(事件、数据){
(侦听器[事件]| |[]).forEach(h=>h(数据))
},
打开(事件、处理程序){
如果(!侦听器[event])侦听器[event]=[]
侦听器[事件]。推送(处理程序)
return()=>host.off(事件、处理程序)
},
一次(事件、处理程序){
如果(!侦听器[event])侦听器[event]=[]
侦听器[event].push(函数h(){
处理程序(…参数)
主机关闭(事件,h)
})
},
关闭(事件、处理程序){
常量i=(侦听器[事件]| |[])。findIndex(h=>h==handler)
如果(i>-1){
侦听器[event].splice(i,1)
如果(!侦听器[event].length)删除侦听器[event]
}
}
})
//范例
常数e=发射器()
e、 一次('msg',msg=>{
console.log('once.msg:',msg)
})
e、 在('msg',msg=>{//{
log('on_1.msg:',msg)
})
e、 emit('msg','See me?')
这是因为
(监听器[事件]|【】)。forEach(h=>h(数据))
将使用一个从
0开始的索引器,并为每个项目递增。当您删除一个项目时(当调用
一次
,调用
关闭
),索引是错误的,实际上会跳过行中的下一项

解决此问题的最简单方法是复制事件:

(listeners[event] || []).slice().forEach(h => h(data));

根据这个答案,一个简单的解决方案是将
侦听器[event]替换为
侦听器[event][i]=function(){};
,在不更改索引的情况下禁用它。使用
集替换数组
,现在似乎可以正常工作,因为没有排序。谢谢:D