new Map的妙用
阿新 • • 發佈:2018-11-08
const actions = new Map([
[1, ['processing','IndexPage']],
[2, ['fail','FailPage']],
[3, ['fail','FailPage']],
[4, ['success','SuccessPage']],
[5, ['cancel','CancelPage']],
['default', ['other','Index']]
])
/** * 按鈕點選事件 * @param {number} status 活動狀態:1 開團進行中 2 開團失敗 3 商品售罄 4 開團成功 5 系統取消 */
const onButtonClick = (status)=>{ let action = actions.get(status) || actions.get('default') sendLog(action[0]) jumpTo(action[1]) }
const actions = new Map([ ['guest_1', ()=>{/*do sth*/}], ['guest_2', ()=>{/*do sth*/}], ['guest_3', ()=>{/*do sth*/}], ['guest_4', ()=>{/*do sth*/}], ['guest_5', ()=>{/*do sth*/}],
['master_1', ()=>{/*do sth*/}],
['master_2', ()=>{/*do sth*/}],
['master_3', ()=>{/*do sth*/}],
['master_4', ()=>{/*do sth*/}],
['master_5', ()=>{/*do sth*/}],
['default', ()=>{/*do sth*/}],
])
/** * 按鈕點選事件 * @param {string} identity 身份標識:guest客態 master主態 * @param {number} status 活動狀態:1 開團進行中 2 開團失敗 3 開團成功 4 商品售罄 5 有庫存未開團 */
const onButtonClick = (identity,status)=>{
let action = actions.get(`${identity}_${status}`) || actions.get('default')
action.call(this)
}
const actions = ()=>{ const functionA = ()=>{/*do sth*/} const functionB = ()=>{/*do sth*/} return new Map( [/^guest_[1-4]$/,functionA], [/^guest_5$/,functionB], //... ]) } const onButtonClick = (identity,status)=>{ let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) action.forEach(([key,value])=>value.call(this)) } 這裡Map的優勢更加凸顯,可以用正則型別作為key了,這樣就有了無限可能,假如需求變成,凡是guest情況都要傳送一個日誌埋點,不同status情況也需要單獨的邏輯處理,那我們可以這樣寫:
const actions = ()=>{ const functionA = ()=>{/*do sth*/} const functionB = ()=>{/*do sth*/} const functionC = ()=>{/*send log*/} return new Map([ [/^guest_[1-4]$/,functionA], /^guest_5$/,functionB], /^guest_.*$/,functionC], //... ]) }
const onButtonClick = (identity,status)=>{ let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) action.forEach(([key,value])=>value.call(this)) }
這樣寫用到了es6裡的Map物件,是不是更爽了?Map物件和Object物件有什麼區別呢?
- 一個物件通常都有自己的原型,所以一個物件總有一個"prototype"鍵。
- 一個物件的鍵只能是字串或者Symbols,但一個Map的鍵可以是任意值。
- 你可以通過size屬性很容易地得到一個Map的鍵值對個數,而物件的鍵值對個數只能手動確認。
const actions = new Map([ ['guest_1', ()=>{/*do sth*/}], ['guest_2', ()=>{/*do sth*/}], ['guest_3', ()=>{/*do sth*/}], ['guest_4', ()=>{/*do sth*/}], ['guest_5', ()=>{/*do sth*/}],
當然上述程式碼如果用Object物件來實現也是類似的:
const actions = {
'guest_1':()=>{/*do sth*/}, 'guest_2':()=>{/*do sth*/}, //.... } const onButtonClick = (identity,status)=>{ let action = actions[`${identity}_${status}`] || actions['default'] action.call(this) }
如果有些同學覺得把查詢條件拼成字串有點彆扭,那還有一種方案,就是用Map物件,以Object物件作為key:
const actions = new Map([
[{identity:'guest',status:1},()=>{/*do sth*/}], [{identity:'guest',status:2},()=>{/*do sth*/}], //... ]) const onButtonClick = (identity,status)=>{ let action = [...actions].filter(([key,value])=>(key.identity == identity && key.status == status)) action.forEach(([key,value])=>value.call(this)) }
我們現在再將難度升級一點點,假如guest情況下,status1-4的處理邏輯都一樣怎麼辦,最差的情況是這樣:
const actions = new Map([
[{identity:'guest',status:1},()=>{/* functionA */}], [{identity:'guest',status:2},()=>{/* functionA */}], [{identity:'guest',status:3},()=>{/* functionA */}], [{identity:'guest',status:4},()=>{/* functionA */}], [{identity:'guest',status:5},()=>{/* functionB */}], //... ])
好一點的寫法是將處理邏輯函式進行快取:
const actions = ()=>{
const functionA = ()=>{/*do sth*/}
const functionB = ()=>{/*do sth*/}
return new Map([
[{identity:'guest',status:1},functionA],
[{identity:'guest',status:2},functionA],
[{identity:'guest',status:3},functionA],
[{identity:'guest',status:4},functionA],
[{identity:'guest',status:5},functionB],
//... ])
}
const onButtonClick = (identity,status)=>{
let action = [...actions()].filter(([key,value])=>(key.identity == identity && key.status == status))
action.forEach(([key,value])=>value.call(this))
}
這樣寫已經能滿足日常需求了,但認真一點講,上面重寫了4次functionA還是有點不爽,假如判斷條件變得特別複雜,比如identity有3種狀態,status有10種狀態,那你需要定義30條處理邏輯,而往往這些邏輯裡面很多都是相同的,這似乎也是筆者不想接受的,那可以這樣實現:
const actions = ()=>{ const functionA = ()=>{/*do sth*/} const functionB = ()=>{/*do sth*/} return new Map( [/^guest_[1-4]$/,functionA], [/^guest_5$/,functionB], //... ]) } const onButtonClick = (identity,status)=>{ let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) action.forEach(([key,value])=>value.call(this)) } 這裡Map的優勢更加凸顯,可以用正則型別作為key了,這樣就有了無限可能,假如需求變成,凡是guest情況都要傳送一個日誌埋點,不同status情況也需要單獨的邏輯處理,那我們可以這樣寫:
const actions = ()=>{ const functionA = ()=>{/*do sth*/} const functionB = ()=>{/*do sth*/} const functionC = ()=>{/*send log*/} return new Map([ [/^guest_[1-4]$/,functionA], /^guest_5$/,functionB], /^guest_.*$/,functionC], //... ]) }
const onButtonClick = (identity,status)=>{ let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) action.forEach(([key,value])=>value.call(this)) }