公司做了個搶紅包的限制,然后ajax請求的返回字段,要進行多層邏輯的判斷,想想是真惡心,雖然都是簡單邏輯,而且看別人以前寫的代碼,發現,哎,注釋能不能寫上吶,像我寫代碼都是細致到,哪怕初學者也能看懂這是要實現什么,還有盡量避免深層次的if嵌套,不然后面產品要加新需求,條件限制了,來個五六個if嵌套,,想想都蛋疼了,故而就查詢了一下如何優化,然后把之前的代碼給重新整理了下,哎,強迫症又犯了,明明不是自己挖的坑,還是想填了!
那么問題來了,在js開發中,如何減少if else語句的使用
代碼中嵌套的if/else結構往往導致代碼不美觀,也不易於理解。面向過程的開發中代碼有大量的IF ELSE,在java中可以用一些設計模式替換掉這些邏輯,那么在js中是否也有類似的方法用來盡可能減少代碼中的if/else嵌套呢?
有人認為:if else多就多唄,只要可讀性強,維護起來方便。jQuery.fn.init里就是一堆if else判斷,難道要質疑jQuery作者的水平了?並不是說if else多就不好,關鍵是看用的地方,jQuery.fn.init里除了if else判斷簡潔點,難道要改成switch?就算用工廠模式,還不是得做大量的if判斷。
代碼整潔強迫症患者必須要來個拋磚引玉:
1.
-
if(a為真){
-
a=a
-
}else{
-
a=b
-
}
-
可寫成:a = a || b
2.
-
if(a==b)
{
-
a=c
-
}
else
{
-
a=d
-
}
可寫成:a = (a==b) ? c : d
3.
后台接口通常會返回這種數據:
fruit: 0 // 0=蘋果,1=梨子,2=桔子,3=檸檬,4=芒果...
這時寫if...else是最痛苦的。從沖哥那偷來個方法:
-
var _f = [
'蘋果',
'梨子',
'桔子',
'檸檬',
'芒果'];
-
shuiguo = _f[fruit];
建議:
第一步:優化if邏輯
人們考慮的東西到時候,都會把最可能發生的情況先做好准備。優化if邏輯的時候也可以這樣想:把最可能出現的條件放在前面,把最不可能出現的條件放在后面,這樣程序執行時總會按照帶啊名的先后順序逐一檢測所有的條件,知道發現匹配的條件才會停止繼續檢測。
if
的優化目標:最小化找到分支之前所判斷條件體的數量。if優化的方法:將最常見的條件放在首位。
-
if (i <
5) {
-
// 執行一些代碼
-
}
else
if (i >
5 && i <
10) {
-
// 執行一些代碼
-
}
else {
-
// 執行一些代碼
-
}
例如上面這個例子,只有在 i
值經常出現小於5的時候是最優化的。如果i值經常大於或者等於10的話,那么在進入正確的分支之前,就必須兩次運算條件體,導致表達式的平均運算時間增加。 if
中的條件體應該總是按照從最大概率到最小概率排列,以保證理論速度最快。
第二步:盡量少使用else
如果在函數中,可以使用 if + return
,先判斷錯誤條件,然后立馬結束函數,防止進入 else
分支。
舉個簡單的例子,后端返回數據,前端根據狀態進行不同操作
-
$.ajax().done(function (res) {
-
if (res.state === 'SUCCESS') {
-
//TODO
-
} else if (res.state === 'FAIL') {
-
//TODO
-
} else {
-
//TODO
-
}
-
});
-
這里用if else不挺好的么,有啥問題么?不過我個人傾向於switch。
解決方法:
1. switch/case
switch和if else在性能上是沒有什么區別的,主要還是根據需求進行分析和選擇。
-
如果條件較小的話選用if else比較合適。
-
相反,條件數量較大的話,就建議選用switch。
一般來說,if else適用於兩個離散的值或者不同的值域。如果判斷多個離散值,使用switch更加合適。
在大多數的情況下switch比if else運行的更加快。
在大多數情況下,switch的性能不會比if else低。switch的確在實質上跟if else if 完全一樣的效果,不過在很多情況下,使用switch要比if else方便不少
比如經典的值等分支,匹配一些狀態常量的時候,比if else結構方便許多,不用反復寫xx == yy
-
$.ajax().done(function (res) {
-
switch (res.state) {
-
case 'SUCCESS':
-
//TODO
-
break;
-
case 'FAIL':
-
//TODO
-
break;
-
default :
-
//TODO
-
}
-
});
-
注意:千萬不要忘記在每一個case語句后面放一個break語句。也可以放一個return或者throw。case語句匹配expression是用===而不是==。
2.hash 表
-
if (key ==
"Apple") {
-
val =
"Jobs";
-
}
else
if (key ==
"microsoft"){
-
val =
"Gates";
-
}
else
if (key ==
"Google"){
-
val =
"Larry";
-
}
這個也可以用 switch case
解決,不過推薦的方法是 hash 表:
-
var ceos = {
"Apple":
"Jobs",
"microsoft":
"Gates",
"Google":
"Larry"};
-
val = ceos[key];
3.重構,用 OO 里面的繼承或者組合
-
1.如果是狗,則汪汪
-
2.如果是貓,則喵喵
-
3.如果是羊,則咩咩
-
4.如果是鴨,則嘎嘎
可以重構一下,改成 OO。
-
*定義類: 動物(或者接口)
-
*定義方法:叫
-
*定義子類:狗、貓、羊、鴨
-
*重寫方法
---- 叫
也就是說將同的判斷按照功能,寫成函數,這樣也便於閱讀
比如我有一個方法根據類型獲取名稱,用if else會這樣
-
function getName(type) {
-
if (
type ===
'monkey') {
-
return
'monkey name';
-
}
else
if (
type ===
'cat') {
-
return
'cat name';
-
}
else {
-
return
'dog name';
-
}
-
}
如果寫成函數,改成下面的會更好
-
function getName(type) {
-
var
data = {
-
monkey:
'monkey name',
-
cat:
'cat name',
-
dog:
'dog name'
-
}
-
-
return
data[type] ?
data[type] :
data[
'dog'];
-
}
硬要把設計模式添加到JS里不是不可以,但是要看情況。生搬硬套過來的東西然並卵啊。寫代碼記住三個字即可,短簡易。代碼短,讀起來簡單,維護容易,如果在性能和代碼長度上二選一,我肯定選代碼短,性能不行,加台服務器就是了。而冗長的代碼並不是加個程序員就能搞定的。
保持着這個心態寫代碼,寫出的東西離設計模式也不會差太多了。