JS 邏輯判斷不要只知道用 if-else 和 switch條件判斷(小技巧)
我們在編寫 JS 代碼時,經(jīng)常會遇到邏輯判斷復雜的情況。一般情況下,可以用 if/else 或 switch 來實現(xiàn)多個條件判斷,但會出現(xiàn)一個問題:隨著邏輯復雜度的增加,代碼中的 if/else 和 switch 會越來越臃腫。本文將帶你嘗試寫出更優(yōu)雅的判斷邏輯。
比如說下面這樣一段代碼:
const onButtonClick = (status) => { if (status == 1) { sendLog('processing') jumpTo('IndexPage') } else if (status == 2) { sendLog('fail') jumpTo('FailPage') } else if (status == 3) { sendLog('fail') jumpTo('FailPage') } else if (status == 4) { sendLog('success') jumpTo('SuccessPage') } else if (status == 5) { sendLog('cancel') jumpTo('CancelPage') } else { sendLog('other') jumpTo('Index') } }
你可以在代碼中看到這個按鈕的點擊邏輯。根據(jù)活動狀態(tài)的不同做兩件事,發(fā)送日志埋點并跳轉(zhuǎn)到相應(yīng)的頁面。很容易想到這段代碼可以用 switch 重寫如下:
const onButtonClick = (status) => { switch (status) { case 1: sendLog('processing') jumpTo('IndexPage') break case 2: case 3: sendLog('fail') jumpTo('FailPage') break case 4: sendLog('success') jumpTo('SuccessPage') break case 5: sendLog('cancel') jumpTo('CancelPage') break default: sendLog('other') jumpTo('Index') break } }
好吧,看起來比 if/else 層次結(jié)構(gòu)更清晰一些,細心的讀者可能也發(fā)現(xiàn)了一個小竅門:case 2 和 case 3 的邏輯一樣時,可以把前面的邏輯處理代碼省略,case 2 會自動執(zhí)行與 case 3 的邏輯。
不過,還有一個更簡單的寫法:
const actions = { '1': ['processing', 'IndexPage'], '2': ['fail', 'FailPage'], '3': ['fail', 'FailPage'], '4': ['success', 'SuccessPage'], '5': ['cancel', 'CancelPage'], default: ['other', 'Index'], } const onButtonClick = (status) => { let action = actions[status] || actions['default'], logName = action[0], pageName = action[1] sendLog(logName) jumpTo(pageName) }
上面的代碼看起來確實比較干凈,這種方法的巧妙之處在于,它把判斷條件作為對象的屬性名,把處理邏輯作為對象的屬性值。在點擊按鈕的時候,這種方法特別適用于單項條件判斷的情況,即通過對象屬性查找的方式進行邏輯判斷。
這個方法很好,但是有沒有其他的方法來編碼呢?有的!
const actions = new Map([ [1, ['processing', 'IndexPage']], [2, ['fail', 'FailPage']], [3, ['fail', 'FailPage']], [4, ['success', 'SuccessPage']], [5, ['cancel', 'CancelPage']], ['default', ['other', 'Index']], ]) const onButtonClick = (status) => { let action = actions.get(status) || actions.get('default') sendLog(action[0]) jumpTo(action[1]) }
使用 Map 代替 Object 有很多優(yōu)點,Map 對象和普通對象有的區(qū)別是:
- 一個對象通常有自己的原型,所以一個對象總是有一個“prototype”鍵
- 對象的鍵只能是一個字符串或符號,但 Map 的鍵可以是任何值
- 你可以通過使用 size 屬性很容易得到 Map 中的鍵值對的數(shù)量,而一個對象中的鍵值對數(shù)量不能直接獲取
現(xiàn)在我們來升級一下這個問題的難度。點擊按鈕時,不僅要判斷狀態(tài),還要判斷用戶的身份。
const onButtonClick = (status, identity) => { if (identity == 'guest') { if (status == 1) { //do sth } else if (status == 2) { //do sth } else if (status == 3) { //do sth } else if (status == 4) { //do sth } else if (status == 5) { //do sth } else { //do sth } } else if (identity == 'master') { if (status == 1) { //do sth } else if (status == 2) { //do sth } else if (status == 3) { //do sth } else if (status == 4) { //do sth } else if (status == 5) { //do sth } else { //do sth } } }
從上面的例子中可以看到,當你的邏輯升級到雙重判斷的時候,你的判斷力就會加倍,你的代碼就會加倍。
如何才能讓代碼更干凈利落呢?
這里有一個解決方案。
const actions = new Map([ ['guest_1', () => {}], ['guest_2', () => {}], ['guest_3', () => {}], ['guest_4', () => {}], ['guest_5', () => {}], ['master_1', () => {}], ['master_2', () => {}], ['master_3', () => {}], ['master_4', () => {}], ['master_5', () => {}], ['default', () => {}], ]) const onButtonClick = (identity, status) => { let action = actions.get(`${identity}_${status}`) || actions.get('default') action.call(this) }
上述代碼的核心邏輯是。將兩個判斷條件拼接成一個字符串作為 Map 的鍵,然后在查詢時直接查詢對應(yīng)字符串的值。當然,我們也可以在這里把 Map 改成 Object。
const actions = { guest_1: () => {}, guest_2: () => {}, //.... } const onButtonClick = (identity, status) => { let action = actions[`${identity}_${status}`] || actions['default'] action.call(this) }
如果讀者覺得把查詢拼成一個字符串有點尷尬,還有另一個解決辦法,那就是用一個 Map 對象作為 key。
const actions = new Map([ [{ identity: 'guest', status: 1 }, () => {}], [{ identity: 'guest', status: 2 }, () => {}], //... ]) const onButtonClick = (identity, status) => { let action = [...actions].filter(([key, value]) => key.identity == identity && key.status == status) action.forEach(([key, value]) => value.call(this)) }
這里你也可以看到 Map 和普通對象的區(qū)別,其中 Map 可以用任何類型的數(shù)據(jù)作為鍵?,F(xiàn)在讓我們把它的難度再提高一點。如果對于 guest 身份來說,狀態(tài) 1-4 的處理邏輯是一樣的呢?
最壞的情況是這樣的(代碼大量重復):
const actions = new Map([ [{ identity: 'guest', status: 1 }, () => {}], [{ identity: 'guest', status: 2 }, () => {}], [{ identity: 'guest', status: 3 }, () => {}], [{ identity: 'guest', status: 4 }, () => {}], [{ identity: 'guest', status: 5 }, () => {}], //... ])
更好的方法是把處理邏輯函數(shù)分離出來:
const actions = () => { const functionA = () => {} const functionB = () => {} 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)) }
這對于日常需求來說已經(jīng)足夠了,但是說真的,函數(shù) A 被引用了 4 次,還是有點煩人。
如果事情真的變得很復雜,比如身份有 3 種,狀態(tài)有 10 種,你需要定義 30 個處理邏輯,其中很多處理邏輯都是一樣的,這似乎讓人無法接受。
而你可以這樣做:
const actions = () => { const functionA = () => {} // 邏輯處理 A const functionB = () => {} // 邏輯處理 B 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 而不是 Object 的優(yōu)勢比較明顯,因為可以用正則式作為鍵。
如果需求變成:所有的對 guest 操作都需要發(fā)送一個日志埋點,不同狀態(tài)的 guest 可能有不同的邏輯處理,那么我們可以寫成如下:
const actions = () => { const functionA = () => {} // 邏輯處理 A const functionB = () => {} // 邏輯處理 B const functionC = () => {} // 發(fā)送日志 C 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)) }
這樣一來,公共邏輯和單個邏輯可以同時執(zhí)行。
總結(jié)
本文講到了八種 JS 邏輯判斷的寫法,包括:
- if/else
- switch
- 單一判斷:存儲在 Object 中
- 單一判斷:存儲在 Map 對象中
- 多重判斷:將條件串聯(lián)成一個字符串,存儲在 Object 中
- 多重判斷:將條件連成一個字符串,存儲在 Map 對象中
- 多重判斷:把條件作為對象存儲在 Map 中
- 多重判斷:把條件寫成正則式存儲在 Map 中
到此這篇關(guān)于JS 邏輯判斷不要只知道用 if-else 和 switch條件判斷的文章就介紹到這了,更多相關(guān)js 邏輯判斷if else switch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
發(fā)布一個高效的JavaScript分析、壓縮工具 JavaScript Analyser
發(fā)布一個高效的JavaScript分析、壓縮工具 JavaScript Analyser...2007-11-11postman自定義函數(shù)實現(xiàn) 時間函數(shù)的思路詳解
Postman是一款功能強大的網(wǎng)頁調(diào)試與發(fā)送網(wǎng)頁HTTP請求的Chrome插件。這篇文章主要給大家介紹postman自定義函數(shù)實現(xiàn) 時間函數(shù)的思路詳解,感興趣的朋友一起看看吧2019-04-04JavaScript實現(xiàn)數(shù)組去重的14種方法大全
親愛的小伙伴,對于數(shù)組javascript中的數(shù)組去重方法你知道多少種呢?學會如何對數(shù)組進行去重對于javascript的學習來說也是十分重要的,下邊就讓我來分享一下我所知道的集中數(shù)組去重的方法吧,感興趣的小伙伴跟著小編一起來看看吧2025-03-03