條件判斷
口語上常說的「如果」、「假設」是控制程式運行流程的關鍵語法。
if-else
條件式為 true 時就會執行內容:
const a = 1;
if (a > 0) { console.log('a 大於 0'); // a > 0 為 true 所以會執行}會自動轉型為 true 的是真值 (truthy),false 是假值 (falsy) 。
以下都會轉為假值:
undefined0''(空字串)nullNaN
if (message) { console.log('有訊息:', message);} else { console.log('沒有訊息'); // 訊息如果是空字串、undefined、null 等}因此條件判斷除了大於、小於等數值比較,也經常用在判定某些內容是否存在。
switch
需要傳入一個值,然後列舉對應的情境 (case) 與執行內容:
const letter = 'A';
switch (typeof letter) { case 'string': console.log('這是字串'); break; default: console.log('不是字串');}case 中如果沒有 break 或 return,判斷會一直執行下去。
switch 通常用來列舉一個值可能會出現哪些。
下面是一個語意上看起來正確,但實際上有問題的用法:
let wallet = 300;
switch (wallet) { case wallet > 500: console.log('給我一瓶酒再給我一支菸'); break; case wallet > 100: console.log('快把我的悲傷都帶走'); break; default: console.log('把愛勇氣希望都賣了能換來多少錢');}
// 印出 '把愛勇氣希望都賣了能換來多少錢'所以看起來好像要執行 case wallet > 100 並印出 '快把我的悲傷都帶走',但最後執行了 default 的內容,因為 300 > 100 雖然是對的,但這個條件式回傳的是 true,所以實際上變成 case true:。
要執行哪個 case,是看 switch () 括號中的值和 case 的值是否相等,而 switch (300) 並不等於 case true。
要進到 wallet > 100 這個 case,只要把 switch(wallet) 改成 switch(true) 即可,
但一般不這麼做是因為不符合語意。
三元運算
如果條件判斷只是單純地看某個變數的真假值,並且需要一個回傳值,可以用三元運算簡化程式碼長度:
const result = getData();
// if else 的寫法if (result) { console.log('有資料');} else { console.log('沒資料');}
// 三元運算的寫法console.log(result ? '有資料' : '沒資料');也可以寫一些程式碼進去執行,如下面範例,但個人覺得三元運算單純用在簡單的取值就好:
const message = getMessage();
// 不好的寫法message ? console.log('有訊息') : console.log('沒訊息');
// 好一點的寫法console.log(message ? '有訊息' : '沒訊息');
// 這樣也可以const message = getMessage() ? '有訊息' : '沒訊息';console.log(message);連續條件判斷也可以這樣斷行,但我個人不太會這樣寫:
const letter = 'A';
typeof letter === 'string' ? '這是字串' : typeof letter === 'number' ? '這是數字' : typeof letter === 'boolean' ? '這是布林值' : typeof letter === 'object' ? '這是物件' : typeof letter === 'undefined' ? '這是 undefined'短路求值
邏輯運算子 (operator) 會判斷左右兩邊內容的真假值並回傳原始值。每種運算子的真假值判斷方式不同,有可能會提前終止並回傳結果,類似電路的短路概念。
如果原始值本身就是我們需要的內容,就可以使用短路求值來精簡程式碼。
OR
- 一邊為
true就成立 - 返回第一個真值的原始值
例如:getData() 會得到一個陣列或 null,搭配 OR 運算就可以保證 data 最後不會是 null,防止一些意外操作:
// 假設 getData 會回傳陣列或 nulllet data = getData() || [];
console.log(data); // 印出原始陣列或是 [],不會有 nullAND
- 兩邊為
true才成立,並回傳右邊的值 false會提前返回:
console.log('有東西' && '真的有東西'); // '真的有東西'console.log(null && '有東西'); // nullconsole.log(null && undefined); // null空值合併運算子 (Nullish Coalescing Operator)
- 左邊是
null或undefined時回傳右邊的值
console.log(null ?? '有東西'); // '有東西'console.log('' ?? '這裡也有東西'); // ''提前排除例外
實作上有時會忘記排除不合法的值,導致後續對著 null 或 undefined 等等不能操作的資料進行運算,接著產生報錯。
所以通常會在運算前進行一連串的過濾:
function showBodyCondition(bmi) { // 把不合法的條件移到第一個 if (isNaN(bmi) || typeof bmi !== 'number') { console.log('請輸入合法的數字'); } else if (bmi < 17.5) { console.log('過輕'); } //...}early return 也是很常使用的技巧。
函式內只要執行到 return 就會脫離函式,後面的程式碼就不會繼續執行,如下面範例,showPokemonData 一開始就先判斷資料是否還在讀取或者資料不存在:
function showPokemonData(data) { if (isLoading || !data) { return; }
console.log(data);}小結
if-else與switch的使用情境與差異- 運用三元運算與短路求值來簡化程式碼
- 任何資料運算開始前都要檢查,提前排除例外