1. 程式人生 > >new Map的妙用

new Map的妙用

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]) }    

這樣寫用到了es6裡的Map物件,是不是更爽了?Map物件和Object物件有什麼區別呢?

  1. 一個物件通常都有自己的原型,所以一個物件總有一個"prototype"鍵。
  2. 一個物件的鍵只能是字串或者Symbols,但一個Map的鍵可以是任意值。
  3. 你可以通過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*/}],
  ['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) }

當然上述程式碼如果用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)) }