//基於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