讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議24:優化if邏輯 >

建議24:優化if邏輯

邏輯順序體現了人的思維的條理性和嚴密性。合理的順序可以提升解決問題的品質,相反,混亂的順序很容易導致各種錯誤的發生。在分支結構中經常需要面臨各種優化邏輯順序的問題。

人在思考問題時,一般總會對各種最可能發生的情況做好準備,這叫做「有備而來」。分支結構中各種條件根據情況的先後、輕重來排定順序。如果把最可能的條件放在前面,把最不可能的條件放在後面,這樣程序在執行時總會按照代碼先後順序逐一檢測所有條件,直到發現匹配的條件時才停止繼續檢測。如果把最可能的條件放在前面,就等於降低了程序的檢測次數,自然也就提升了分支結構的執行效率,避免空轉,這在大批量數據檢測中效果非常明顯。例如,對於一個論壇系統來說,普通會員的數量要遠遠大於版主和管理員的數量。換句話說,大部分登錄的用戶都是普通會員,如果把普通會員的檢測放在分支結構的前面,就會減少計算機檢測的次數。

if優化目標:最小化找到正確分支之前所判斷條件體的數量。if優化方法:將最常見的條件體放在首位。例如:


if(value<5){

//do something

}else if(value>5&&value<10){

//do something

}else{

//do something

}


這段代碼只有在value值經常小於5時才是最優的。如果value經常大於或等於10,那麼在進入正確分支之前,必須兩次運算條件體,導致表達式的平均運行時間增加。if中的條件體應當總是按照從最大概率到最小概率的順序排列,以保證理論運行速度最快。

另外一種減少條件判斷數量的方法:將if編寫成一系列嵌套結構。使用一個單獨的一長串的if結構通常導致運行緩慢,因為每個條件體都要被計算,例如:


if(value==0){

return result0;

}else if(value==1){

return result1;

}else if(value==2){

return result2;

}else if(value==3){

return result3;

}else if(value==4){

return result4;

}else if(value==5){

return result5;

}else if(value==6){

return result6;

}else if(value==7){

return result7;

}else if(value==8){

return result8;

}else if(value==9){

return result9;

}else{

return result10;

}


在這個if結構中,所計算的條件體的最大數目是10。如果假設value的值在0~10之間均勻分佈,那麼會增加平均運行時間。為了減少條件判斷的數量,可重寫為一系列嵌套結構,例如:


if(value<6){

if(value<3){

if(value==0){

return result0;

}else if(value==1){

return result1;

}else{

return result2;

}

}else{

if(value==3){

return result3;

}else if(value==4){

return result4;

}else{

return result5;

}

}

}else{

if(value<8){

if(value==6){

return result6;

}else{

return result7;

}

}else{

if(value==8){

return result8;

}else if(value==9){

return result9;

}else{

return result10;

}

}

}


重寫if結構後,每次抵達正確分支時最多通過4個條件判斷。新的if結構使用二分搜索法將值域分成了一系列區間,然後逐步縮小範圍。當數值範圍分佈在0~10時,此代碼的平均運行時間大約是前面代碼的一半。此方法適用於需要測試大量數值的情況,而相對離散值來說switch更合適。

當然,在性能影響不是很大的情況下,遵循條件檢測的自然順序會更容易閱讀。例如,對於檢測週一到週五值日任務安排的分支結構來說,雖然週五的任務比較重要,但是這類任務有著明顯的順序,安排順序結構還是遵循它的自然邏輯比較好。如果打亂條件的順序,把週五的任務安排在前面,對於整個分支結構的執行性能沒有太大的幫助,並且不方便閱讀代碼。考慮到這一點,按自然順序來安排結構會更富可讀性。

應注意分支之間的順序優化,當然在同一個條件表達式內部也應該考慮邏輯順序問題。在執行邏輯「與」或邏輯「或」運算時,有可能會省略右側表達式的計算,如果希望不管右側表達式是否成立都進行計算,就應該考慮邏輯順序問題。例如,有兩個條件a和b,其中條件a多為true,b就是一個必須執行的表達式,那麼下面的邏輯順序設計就欠妥當:


if(a&&b){

}


如果條件a為false,則JavaScript會忽略表達式b的計算。如果b表達式影響到後面的運算,那麼不執行表達式b自然會對後面的邏輯產生影響,這時可以採用下面的邏輯結構,在if結構前先執行表達式b,這樣即使條件a的返回值為false,也能夠保證表達式b被計算。


var c=b;

if(a&&b){

}