if else 與 switch 的使用時機
日常生活中充滿了各式各樣的邏輯判斷:「如果」怎樣,就去做某件事,「否則」就去做另外一件事。
「如果降雨機率超過30%,就帶傘!」每天早上出門要做的判斷。
「如果肚子餓了,就吃香蕉!」這是猴子也會的事情!
而上帝也教你怎麼做判斷,古早的聖經就說了:
「如果有人打你的右臉,連左臉也轉過來由他打!」我的臉好腫呀!
if…else
「如果 A 條件成立,就做甲這件事!否則就做乙這件事!」這句話,其實是一個條件式,可以轉換為布林值來判斷:
- 「如果A條件成立」就是 A 條件為true的情況。
- 「否則…」就是 A 條件為 false 的情況。
寫成JavaScript就會是這樣子:
if (條件式){
//條件成立(true)的話,執行{ 甲 }區塊內的內容
}
else {
//如果條件不成立(false),執行{ 乙 }區塊中的內容
}
如果條件不只一個,可以使用 else…if 來新增條件。
if (條件式 1){
//條件1成立(true)的話,執行{ 甲 }區塊內的內容
}
else if (條件式 2){
//條件2成立(true)的話,執行{ 乙 }區塊內的內容
}
else if (條件式 3){
//條件3成立(true)的話,執行{ 丙 }區塊內的內容
}
else {
//如果上面的條件都不成立(false),執行{ 丁 }區塊中的內容
}
補充一點, if 跟 else 在一個邏輯判斷流程中只能使用一次,但是 else if 卻可以使用很多次。
讓我們繼續請郭靖….他爹來示範「if….else….」的用法:
話說郭靖他爹郭嘯天與楊康他爹楊鐵心在妻子懷孕的時候就約定,如果孩子生出來都是男生,就結拜為兄弟;如果是一男一女就結為夫妻。
//guoChildSex代表郭家的孩子,yangChildSex代表楊家的孩子,因為孩子未出生,還不知性別。
let guoChildSex = 'male';
let yangChildSex = 'female';
if ( guoChildSex === yangChildSex ){
console.log('郭家孩子與楊家孩子結拜為金蘭');
}else {
console.log('郭家孩子與楊家孩子結為夫妻');
}
//考慮到多元成家的話,邏輯會更複雜,這個....我們就先停在這裡
這是一個簡單的雙向分歧決策,但是如果是更複雜的情況呢?我們看看下個例子:
話說在《射鵰英雄傳》中,長春子丘處機在嘉興酒樓和江南七怪比賽喝酒這一段十分精彩。但是七怪有七個人,到底要派誰出去呢?猜拳嗎?
讓我們請 JavaScript 來幫我們決定人選吧!
我想隨機選出 1 到 7 之間的數字,從七個人中選出一個來跟丘處機鬥酒,例如數字等於1就印出「飛天蝙蝠–柯鎮惡出來喝酒」,數字等於2就印出「妙手書生–朱聰出來喝酒」,依此類推。
Math.random() 會隨機產生 0 到 1 之間的小數。 而 Math.ceil(x) 會將x無條件進位。
//Math.random() 會隨機產生 0 到 1 之間的小數。 而 Math.ceil(x) 會將x無條件進位。
let drinkWineOrder = Math.ceil(Math.random()*7);
if(drinkWineOrder===1){
console.log('飛天蝙蝠--柯鎮惡出來喝酒');
}
else if (drinkWineOrder===2){
console.log('妙手書生--朱聰出來喝酒');
}
else if (drinkWineOrder===3){
console.log('馬王神--韓寶駒出來喝酒');
}
else if (drinkWineOrder===4){
console.log('南山樵子--南希仁出來喝酒');
}
else if (drinkWineOrder===5){
console.log('笑彌陀--張阿生出來喝酒');
}
else if (drinkWineOrder===6){
console.log('鬧市俠隱--全金發出來喝酒');
}
else{
console.log('越女劍--韓小瑩出來喝酒');
}
寫了這麼落落長的一段,看得眼都花了,if … else … 跑了7次小括號裡面的條件,也判斷了 7 次,這種邏輯判斷稱之為「多向分歧決策」。
switch
JavaScript 還有另一種的 switch 條件判斷式,比較適合這樣的情況,它的寫法是這樣的:
switch (expression) {
case value1:
//當 expression 的值符合 value1
//要執行的陳述句
[break;]
case value2:
//當 expression 的值符合 value2
//要執行的陳述句
[break;]
...
case valueN:
//當 expression 的值符合 valueN
//要執行的陳述句
[break;]
[default:
//當 expression 的值都不符合上述條件
//要執行的陳述句
[break;]]
}
switch 括號中可以放入「運算式」( switch 語句會先執行指定的 expression ,得到一個值)、「變數」或「值」,然後一一去和 case 後面的值比對,如果兩者相吻合,就得出一個 true 的值,然後執行 true 那個 case 區塊的程式敘述。如果每個 case 都不符合則執行 default 區塊的程式敘述。
當滿足 case 列出來的條件,執行完程式敘述之後,break 指令會中止流程判斷,不去執行後面的 case 條件判斷。
switch(Math.ceil(Math.random()*7)){
case 1:
console.log('飛天蝙蝠--柯鎮惡出來喝酒');
break;
case 2:
console.log('妙手書生--朱聰出來喝酒');
break;
case 3:
console.log('馬王神--韓寶駒出來喝酒');
break;
case 4:
console.log('南山樵子--南希仁出來喝酒');
break;
case 5:
console.log('笑彌陀--張阿生出來喝酒');
break;
case 6:
console.log('鬧市俠隱--全金發出來喝酒');
break;
case 7:
console.log('越女劍--韓小瑩出來喝酒');;
break;
default:
console.log('七個人都喝醉了,認輸!!');
break;
}
使用 switch 之後,程式碼沒有夾雜一堆()與{},看起來簡潔、清楚多了。
if…else 與 switch的差別
前面簡單介紹了 if…else 與 switch 的語法,現在來看看兩者的差異。
「範圍取值」適合使用if…else,「確定取值」則使用switch
如果是「範圍取值」,也就是判斷的示範為區間,適合使用 if… else 語句。
如果是「確定取值」,也就是判斷的結果有明確的值,則使用 switch 是一個不錯的選擇。
讓我們看看下面的這個範例:
郭靖為了與黃蓉約會參加桃花島主黃藥師的考試,依考試成績的範圍,有不一樣的獎賞。
如果用 if….else if 要這樣寫:
//郭靖參加桃花島的黃藥師的考試,考試成績超過85分可以娶黃蓉,不及格就去白陀山養癩蛤蟆
let guoScore = 87;
if(guoScore >= 85){
console.log('郭靖可以得到跟黃蓉約會的資格');
}else if(guoScore < 85 && guoScore >= 70){
console.log('郭靖可以學得黃藥師的一樣功夫');
}else if(guoScore < 70 && guoScore >= 60){
console.log('郭靖可以桃花島一日遊');
}else{
console.log('郭靖考試不及格,去白駝山養養癩蛤蟆');
}
//郭靖可以得到跟黃蓉約會的資格
使用 switch 的寫法,如果原樣照搬 if…else 的寫法的話,會變成這樣:
let guoScore =87;
switch(guoScore){
case (guoScore >= 85): //87 !== true
console.log('郭靖可以得到跟黃蓉約會的資格');
break;
case (guoScore < 85 && guoScore >= 70); //87 !== false
console.log('郭靖可以學得黃藥師的一樣功夫')
break;
case (guoScore < 70 && guoScore >= 60): //87 !== false
console.log('郭靖可以桃花島一日遊');
break;
default:
console.log('郭靖考試不及格,去白駝山養癩蛤蟆');
break;
}
//郭靖考試不及格,去白陀山養養癩蛤蟆
//switch()小括號帶入的是變數guoScore,會判斷為全部條件都不吻合,直接去執行default區塊。
什麼!明明郭靖考了87分,怎麼還要去白陀山養癩蛤蟆!!!這一定有黑幕!!!
等等!別急著打我!讓我來解說一下!
先記得這件事: switch() 括號中的條件跟 case 後面的值比較的結果必須為 true ,才會去執行case 後面的程式碼區塊。
因為每個 case 括號裡的 guoScore 是去跟外面的 let guoScore = 87 比較,比較的結果不是 true 就是 false,其中只有「 case (guoScore >= 85) 」為 true ,其他的範圍區間都是false。
而 switch() 小括號所帶入變數 guoScore 的值為 87 ,去跟每個 case 的布林值比對, 87 不等於true,也不等於false,當然找不到符合的條件,所以就直接去執行所有條件都不成立的 default 區塊。
如果要讓這個 switch 區塊能夠執行,就要這樣寫:
let guoScore = 87;
switch(true){
case (guoScore >= 85): //true == true
console.log('郭靖可以得到跟黃蓉約會的資格');
break;
case (guoScore < 85 && guoScore >= 70): //true !== false
console.log('郭靖可以學得黃藥師的一樣功夫')
break;
case (guoScore < 70 && guoScore >= 60): //true !== false
console.log('郭靖可以桃花島一日遊');
break;
default:
console.log('郭靖考試不及格,去白駝山養癩蛤蟆');
break;
}
//'郭靖可以得到跟黃蓉約會的資格'
由上面可以看出 switch() 的小括號裡帶入的就不是郭靖的分數 guoScore 了,而是布林值 true ,這時去和 case 後面的布林值比對,才會在「 case (guoScore < 80 && guoScore >= 60) 」得到 true === true 相等的結果,進而得到「’郭靖可以得到跟黃蓉約會的資格’」的結果。
這種情況之下,使用 switch 就不如 if…else if… 直觀了。
所以在這裡我們得到的重點是:
- 「 if…else if … 」適合使用在不同的條件區間的判斷,如果都沒符合條件,則執行「 else 」的程式碼。
- 而「switch」適合使用在有明確的「值」的情況下。
switch 是用嚴謹模式( === )在比對 case 後面的數值
最後讓我們用情境題來解釋一下這個情形:
黃藥師對於郭靖考到 87 分非常不爽,於是拿出了三個信封,上面分別寫了”1”、”2”、”3”,要郭靖從裡面挑一個。
讓我們看一下 if…else if 怎麼寫:
let guoPick = "3";
if(guoPick == 1){
console.log('到東海餵鯊魚!');
}else if (guoPick == 2){
console.log('到南海騎烏龜');
}else if(guoPick == 3){
console.log('在桃花島當島主')
}else{
console.log('去白駝山養癩蛤蟆')
}
//在桃花島當島主
運氣好!你打我呀!挑到”3”,可以’在桃花島當島主’。
讓我們看看用 switch 來判斷,會發生甚麼悲劇…
let guoPick = "3";
switch(guoPick){
case 1:
console.log('到東海餵鯊魚!');
break;
case 2:
console.log('到南海騎烏龜');
break;
case 3:
console.log('在桃花島當島主');
break;
default:
console.log('去白駝山養癩蛤蟆');
}
//去白陀山養癩蛤蟆
蛤!為甚麼挑到”3”,還要’去白駝山養癩蛤蟆’!
郭靖的拳頭又硬了!
這是因為switch判斷式是使用嚴格模式,遇到 ‘3’ 這種狀況,會把它當字串處理,所以才會所有 case 條件都不符合,直接去執行 default 區塊。
講了那麼多,前面說的忘記了沒關係,讓我們重點整理一下, switch 與 if…else 的差別與使用時機:
- if…else 適合「單向決策」與「雙向分歧決策」; switch 適合「多向分歧決策」。
- 「範圍取值」適合使用 if…else ;「確定取值」則適合使用 switch 。
- switch 是用嚴謹模式( === )在比對 case 後面的數值
我不是老司機,而是初踏入前端領域的老學徒,如果有寫錯的地方還請大家包涵與指正,謝謝大家!
參考資料