首页
/
每日頭條
/
圖文
/
ifelse的改進
ifelse的改進
更新时间:2024-09-29 11:26:20

面對過多的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

,
Comments
Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
Sign up to post
Sort by
Show More Comments
推荐阅读
模仿秀郭德綱盧鑫玉浩歡樂喜劇人(模仿郭德綱反而赢了)
模仿秀郭德綱盧鑫玉浩歡樂喜劇人(模仿郭德綱反而赢了)
  文/娛樂酸檸檬   3月29日晚間,《歡樂喜劇人》重新開賽,在經曆了長時間的調整後,各組喜劇人們明顯是有備而來,再加上賈冰和崔志佳的強勢助陣,本期競演的5個節目質量爆棚,使得東方衛視同一時段的收視率達到了0.8676%,位居各大衛視台榜首。      當晚的《歡樂喜劇人》競演,個人認為是7期節目中整體質量最好的一期,賈冰的小品切合當下環境,時效性極強;崔...
2024-09-29
15萬到20萬中型suv哪一款值得選擇(綜合性價比比較高的三款中型SUV)
15萬到20萬中型suv哪一款值得選擇(綜合性價比比較高的三款中型SUV)
  對于大部分的消費者來說,20萬左右的中型SUV具有很強的實用價值,畢竟國内大部分這個級别消費者的核心訴求就是為了代步,說白了就是坐着舒服、開着舒服、用着放心,今天我就為大家挑選3款綜合性價比特别高的SUV車型,本田的CR-V、别克昂科威和雪佛蘭探界者。      第一、本田CR-V   當年這個車簡直就是加價神車,耐用省心就是它的标簽,這幾年的銷量也不錯...
2024-09-29
非誠勿擾如何對待感情(男生缺乏儀式感被心動女生拒絕)
非誠勿擾如何對待感情(男生缺乏儀式感被心動女生拒絕)
  一個身穿漢服的男嘉賓來到《非誠勿擾》舞台相親,他是一位漢服的服裝店老闆。也許是因為喜歡漢服,他選擇了台上一位同樣穿着漢服的女嘉賓作為心動女生,兩人無論是外表還是服飾上都非常的般配。不少女嘉賓也隐約感受到她是為了漢服女生而來,因此選擇滅燈讓位。本以為漢服的女生會留燈,沒想到她卻滅了燈,理由是男嘉賓在VCR裡說自己缺乏“儀式感”,而她則是比較看重儀式感這個東...
2024-09-29
c4 picasso 試駕(将藝術帶入工業)
c4 picasso 試駕(将藝術帶入工業)
  MPV時代原創稿件歡迎分享,轉載請注明出處。   十款MPV九款醜,這是很多人的相同看法。不錯,由于中國消費者對MPV的理解比較淺,再加上市面上的MPV絕大多數集中在10萬以内,讓人們認為MPV就是用來拉貨的,所以不少消費者想買一款家用車大多數都會選擇轎車或者SUV。      當然,這種說法并不是正确的,還有我們熟知的中高端MPV。它們基本上都走商務路...
2024-09-29
荒野大镖客2線上版本還需要買嗎(救贖2OL部分不會影響GTAOL)
荒野大镖客2線上版本還需要買嗎(救贖2OL部分不會影響GTAOL)
  Take-Two似乎對《荒野大镖客:救贖2》的OL部分很有自信。在最近的季度财務電話會議上,Take-Two高層Strauss Zelnick被問到《荒野大镖客:救贖2》是否會推出OL部分以及與《GTAOL》的關系時,他是這麼回答的:      “娛樂的體驗是不同的,在這款遊戲中的體驗很難在另外一款遊戲中找到。你不會想‘我現在需要娛樂’。娛樂是你想要一直...
2024-09-29
Copyright 2023-2024 - www.tftnews.com All Rights Reserved