tft每日頭條

 > 圖文

 > ifelse的改進

ifelse的改進

圖文 更新时间:2025-01-26 14:41:01

面對過多的if-else,代碼可能看起來比較冗餘,搞不好又是一張被人到處轉發的“我們項目幾百幾千行if”的圖。但是經過各種設計模式和封裝,if大大減少,但可讀性可能稍微降低了,而且比較抽象。那我們應該如何取舍呢

抛開其他因素,如果if-else過多,可讀性也許會好也可能會降低,可維護性也是或高或低;如果if-else少,代碼高度抽象,可讀性會低或者不變,可維護性可能會高也可能會低。這裡大概可能會有幾種情況

if平鋪條件單一

這種情況,if精簡不精簡,可讀性是不會變的,但是精簡程度和可維護性是正相關的。至于為什麼,看一下代碼就可以感受到了

ifelse的改進(該不該扼殺過多的if-else)1

執行語句單一

if (a === 1) { console.log('this is 1') } else if (a === 2) { console.log('this is 2') } else if (a === 3) { console.log('this is 3') } // ...還有很多 else { console.log('this is other') }

精簡代碼:

// 如果上面的if a是從1到10 console.log(`this is ${a > 0 && a < 10 ? a : 'other'}`) // 如果上面的if a是從1到5和從7-10 if ((a > 0 && a < 5) || (a > 7 && a < 10) { console.log(`this is ${a}`) } else { console.log('this is other') } // a取值靈活區間 const area = [[1,2], [5,7], [10, 11]] console.log(`${area.find(([from, to]) => { return from <= a && a <= to }) ? a : 'other'}`)

這種情況,有沒有精簡,可讀性都沒有發生變化,如果是未精簡的,寫一堆if,你還是很容易看得出幹啥。而可維護性就不一樣了,要加一個或者多個數字,那麼就要深入到某個if分支,一個個動手改,維護性低。但是,如果精簡了的話,維護性大大增加,代碼也簡短。隻需要尋找if的規律并封裝所有的case即可,最後做到“條件驅動”

一些極簡情況

有一些非常簡單的情況,可以使用&&、||、三元解決

// before if (cb) { cb() } //after cb && cb() // before if (!obj) { obj = {} } obj.a = 1 //after (obj || obj = {}).a = 1 // before if (type === true) { value = 1 } else { value = 2 } //after value = type ? 1 : 2 // before if (type === DEL) { this.delateData(id) } else { this.addData(id) } // after this[type === DEL ? 'delateData' : 'addData'](id) // or ;(type === DEL ? this.delateData : this.addData)(id) // before if (a === 1 && a === 2 && a === 10) { console.log('ok') } // after if ([1, 2, 10].includes(a)) { console.log('ok') }

條件單一、執行語句單一的情況,建議優化指數:★★★★★

執行語句複雜

if (a === 1) { console.log('this is 1') } else if (a === 2) { console.log('this is 二') } else if (a === 3) { console.log('this is three') } // ...還有很多 else { console.log('this is other') }

精簡代碼:

const map = { 1: 'this is 1', 2: 'this is 二', 3: 'this is three', // ...很多 } console.log(map[a] || 'this is other')

這種情況,和執行語句單一類似,也是可讀性不變,代碼減少了可維護性隻是略好一點。通常的解決辦法就是k-v映射了。加一個條件,就在map中加多一對k-v(由于條件處理複雜,所以條件上沒有優化空間了,必須寫出來)

這種場景,平時應該會比較常見轉為switch。如果執行語句很複雜無規律,寫k-v的缺陷就來了:一個key被迫對應一個callback函數,還會花時間斟酌傳值問題,而且代碼量也沒發生變化,此時不建議優化

if (a === 1) { console.log('this is 1') alert(a * 100); } else if (a === 2) { console.log('this is 二') document.body.innerHTML = a 1 b } // after const map = { 1: (a) => { console.log('this is 1') alert(a * 100); }, 2: (a, b) => { console.log('this is 二') document.body.innerHTML = a 1 b } } map[a](a, b) // 代碼量并沒有減少也沒有增強維護性 複制代碼

問題來了,條件單一,但處理語句有簡單的也有複雜的怎麼辦?case by case,先歸類再分情況,最終隻會剩下少量if和switch的

小結: 條件單一、執行語句複雜的情況,有規律時建議優化指數:★★★,無規律時,建議指數:★

if平鋪條件複雜

如果條件複雜,執行語句單一,那麼條件可以通過&&、||、三元來簡化,或者是平鋪if-return,問題也迎刃而解。然而,條件複雜,執行語句大概率也是複雜的。

if (a === 1) { console.log(1); } else if (arr.length === 3) { alert('this is length 3 arr'); } else if (a === 2 && b === 1) { console.log(2); console.info('haha'); } else if (a === 2) { console.log(222); document.title = 'a = 2'; } else if (arr.length) { console.error('arr is not empty'); }

都沒有規律可循,那麼就真的沒有進一步方案了。但是我們觀察一下,發現一些條件是有交集的,如a === x,我們可以把這種類型的if抽出來:

const handleA = { 1: () => { console.log(1); }, 2: () => { if (b === 1) { console.log(2); console.info('haha'); } else { console.log(222); document.title = 'a = 2'; } } } const handleArrLen = { 3: () => { alert('this is length 3 arr'); } } if (handleA[a]) { handleA[a]() } else if (arr.length) { ;(handleArrLen[arr.length] || () => { console.log(222); document.title = 'a = 2'; })() }

這樣子,可以把邏輯模塊化,增加可讀性和可維護性,但是犧牲了精簡性。

注意,上面這樣子條件模塊化了,意味着同一類的條件都會歸到一起。如果業務邏輯對if條件有嚴格要求的,比如一定要先判斷a === 1,再看看arr.length === 3,再看a === 2 && b === 1,按照這樣的順序,那就不能這樣做了

還有一種情況,就是if裡面直接調用已經封裝好的函數,沒有其他語句(其實就相當于退化為條件複雜,執行語句簡單了):

if (a === 1) { f1() } else if (arr.length === 3) { f2() } else if (a === 2 && b === 1) { f3() } else if (a === 2) { f4() } else if (arr.length) { f5() }

這種情況(前提條件,不會經常改這裡,如果是經常改,還是會吐血的),減少if後也不賴:

const index = [a === 1, arr.length === 3, a === 2 && b === 1, a === 2, arr.length].findIndex(Boolean) if (index !== -1) { [f1, f2, f3, f4, f5][index]() }

如果所有的else if都是互斥的,沒有交集,那麼換成if-return更好

if (a) { // do xx about a return } if (b) { // do xx about b return }

小結:如果條件複雜,執行語句單一,建議優化指數: ★★★★★;如果執行語句也複雜,當條件可以模塊化的且沒有順序要求,建議優化指數: ★★★★。當條件有嚴格順序要求、無規律可循,不建議強行減少if-else

if條件有嵌套

嵌套實際上就是平鋪的增強,平鋪嵌套平鋪,我們可以當作是多個if平鋪條件複雜的情況來看。例如有如下代碼,我們尋找一些規律來優化一下

if (id === 1) { console.log(1); if (type === 2) { console.log('type2'); } else { console.log('type3'); } } else if (id === 2) { console.log(2); if (type === 3) { console.log('id2 type3'); if (ext === 1) { console.log('ext1'); } } } else { console.log('other id'); }

根據id劃分:犧牲了其他因素的可讀性,但對于id的維護性增強了

const handleId = { 1: () => { console.log(1) console.log(type === 2 ? 'type2' : 'type3') }, 2: () => { console.log(2) // 這裡建議優化指數為★★,可能可讀性低,所以保持現狀也行 // eslint一開,這套涼涼,必須寫回普通if-else type === 3 && (console.log('id2 type3'), ext === 1) && console.log('ext1') } } handleId[type] ? handleId[type]() : console.log('other id')

如果此時根據type劃分,那麼難度大大增加了,這就是人人懼怕的重構了。如果後面業務邏輯,的确是以type為主導的,那重構也是早晚的事情了。所以,前期的設計以及産品邏輯,将會決定後面的維護舒服不舒服了

小結: if條件有嵌套情況,拆分if,其實就是平鋪的if嵌套平鋪的if,如果有規律可循,那麼按照前面的平鋪來減少if。如果沒有規律、也不是邏輯側重的點,那麼就不建議減少if了

總結
  • 條件簡單,執行語句單一,強烈建議減少if-else來優化,用條件驅動結果(&& ||三元或者是自己寫小邏輯)
  • 條件簡單,執行語句複雜,可保持現狀或者換成switch,如果不複雜可以使用map映射
  • 條件複雜,執行語句單一,強烈建議減少if-else來優化;如果執行語句也複雜,當條件可以模塊化的且沒有順序要求,比較建議優化。當條件有嚴格順序要求、無規律可循,不建議任何改動
  • 嵌套if,拆分為平鋪if來判斷如何優化或者不改動

作者:lhyt鍊接:https://juejin.im/post/5e86a0e56fb9a03c4a4966fb

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved