在開發中,實現技能狀態的事件監聽功能時,將狀態對象做爲key,存入事件管理器的監聽列表,以下圖:函數
實現後,運行程序,並無報錯,可是當某個事件發生時,只有一個狀態被觸發監聽,而大多數狀態在建立時,就監聽了該事件,正確的表現應當是全部監聽該事件的狀態對象都被觸發。ui
首先判斷是狀態實現問題,可是每一個狀態都是繼承AbstractState這個父類,並無從新實現父類的事件監聽函數,檢查父類監聽代碼實現,未發現問題。spa
代碼檢查沒有發現問題,看着是正常的,但實際效果確實有問題,因而添加打印,在addEventListener以前打印監聽列表,addEventListener以後也打印監聽列表,對象
打印的結果顯示,addEventListener以前若是監聽列表爲空,那麼addEventListener以後會成功添加一個監聽,可是若是addEventListener以前監聽列表有一個監聽了,那麼addEventListener以後,監聽列表只會剩下最新添加的那個監聽!這就是問題所在了,可是爲何會出現這種狀況呢?爲何新的對象會覆蓋舊的?繼承
將本次遇到的問題簡單化成以下例子:事件
能夠看到,b實際上一直只有一個key,即'[object Object]'這個字符串,變化的只是value,在JS中,建立對象時,不論以什麼類型的值作Key,JS會默認調用toString()方法將該key轉成字符串類型,如數字類型:開發
能夠看到key 1 變成了 '1',而當key時對象時,object.toString()的結果只會等於'[object Object]',以下圖:字符串
這就是上面爲何b對象永遠只會有一個key = '[object Object]'的緣由,JS不支持對象使用toString()方法,即不支持對象以對象作key。it
另外,對象轉字符串,JS提供JSON.Stringify()特殊方法。class
鑑於上面的分析結果,若是仍是執意想要用狀態對象作key的話,可使用JSON.Stringify(state),但這顯得不夠優雅,最後的解決方案是在每一個狀態對象中,增長一個uuid屬性,以該uuid做爲Key,存入監聽列表中。