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 後面的數值

我不是老司機,而是初踏入前端領域的老學徒,如果有寫錯的地方還請大家包涵與指正,謝謝大家!

參考資料

JavaScript 基礎知識-switch & if else 的判別差異

JavaScript switch case

JavaScript switch 語法

Javascript 中 switch 的彈性用法

JavaScript 的 if 跟 switch 效能

switch - 程式碼教學

流程控制 if/else 條件判斷

switch…case && if…else效率比較和優化


if else 與 switch 的使用時機
https://popeye-ux.github.io/2021/10/27/ifElseAndSwitch/
作者
POPEYE
發布於
2021年10月27日
許可協議