//基于es6自己封装发布订阅库 jQ中的发布订阅没有去重的功能 let _subscribe = function(){ //SUB :发布订阅类 class Sub{ constructor(){ //创建一个事件池,用来存储后期需要执行的方法 this.$pond = []; } //给事件池追加方法(做重复处理) add(func){ let flag = this.$pond.some(item=>{ return item === func; }); !flag ? this.$pond.push(func) : null; } //从事件池中移除方法 remove(func){ let $pond = this.$pond; for(let i = 0;i < $pond.length; i++){ let item = $pond[i]; if(item === func){ //移除(顺序不变的情况下基本上只能用splice了,但是不能这样写,这样写会导致数组塌陷问题,我们不能真正移除,只能把当前项赋值为null. // $pond.splice(i,1); $pond[i] = null; break; } } } //通知事件池中的方法,按照顺序执行 fire(...args){ let $pond =this.$pond; for(let i = 0; i< $pond.length;i++){ let item = $pond[i]; if(typeof item !== 'function'){ //此时再删除 $pond.splice(i,1); i--; continue; } item.call(this, ...args) } } } //暴露给外面用 return function subscribe(){ return new Sub(); } }(); //使用 let s1 = _subscribe(); //事件池中移出事件导致的数组塌陷问题:fire的时候通知事件执行时,拿循环的索引i去对应数组的下标,当有事件被移除时,数组发生变化,但是去对应的索引i继续去对应,会导致事件中某几项被跳过. //解决:移除用假装移除,把当前项改成null,这样索引还是不变.真正移除在fire的时候去进行,此时fire时需检查执行的是否为function