if...else
很好用
但當它變得複雜,變得像洋蔥一層又一層的時候... 很痛苦
如果要寫出好讀好寫的 JS,學會怎麼簡化 if...else,是很重要的課題!
題外話:
還記得曾經遇過一個客戶,請工程師協助調整功能
不論我們怎麼解釋....調整這個需求需要花時間卻得到一句 "不就是多加一個 if...else 嗎"
以下範例摘自5 Tips to Write Better Conditionals in JavaScript 介紹五種可以讓條件式寫的更優雅的方法
Array.includes
判斷多種條件function test(fruit) {
if (fruit == 'apple' || fruit == 'strawberry') {
console.log('red');
}
}
當今天如果條件式裡只有一個條件 if (fruit == 'apple')
, 還可以,沒有問題
但如果出現了第二個條件 if (fruit == 'apple' || fruit == 'strawberry')
,就可以考慮改寫了
原因是: fruit
變數可能會重複寫很多次,例如 fruit == 'xxxx'
會一直往後接下去
利用 Array.includes
,判斷某元素是否有出現在陣列中
重構後:
function test(fruit) {
// 將條件寫在 Array 中
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}
}
之後要新增水果,直接異動 redFruits
就好,不用寫在 if 裡!
延續上面的例子
fruit
--> throw Error
太多太多
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 第一層: 是否有 fruit 存在
if (fruit) {
// 第二層: 是否為紅色的水果
if (redFruits.includes(fruit)) {
console.log('red');
// 第三層: 是否超過目標數量(10)
if (quantity > 10) {
console.log('太多太多');
}
}
} else {
throw new Error('水果咧!');
}
}
// 執行結果
test(null); // error: 水果咧
test('apple'); // print: red
test('apple', 20); // print: red, 太多太多
if
--> 不好閱讀重構成:
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 把驗證 fruit 有值與否寫在最前面 --> 驗證失敗 --> throw error (後面的判斷就可以不用看了)
if (!fruit) throw new Error('水果咧'); // 第一關: throw error early
if (!redFruits.includes(fruit)) return; // 第二關: 當水果不在 redFruits 中 --> Return
console.log('red');
// 第三關: 數量是否大於 10
if (quantity > 10) {
console.log('太多太多');
}
}
『 透過 Early Return
來控制流程,減少巢狀的寫法 』
function test(fruit, quantity) {
if (!fruit) return;
const q = quantity || 1; // 數量預設值是 1
console.log(`We have ${q} ${fruit}!`);
}
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
還可以更好的地方--> q 這個變數可以省略宣告
function test(fruit, quantity = 1) { // 預設值直接寫在 parameter 中
if (!fruit) return;
console.log(`We have ${quantity} ${fruit}!`);
}
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
Object
來取代 Switch假設想要依不同的顏色印出對應的水果
function test(color) {
// 利用 switch case
switch (color) {
case 'red':
return ['apple', 'strawberry'];
case 'yellow':
return ['banana', 'pineapple'];
case 'purple':
return ['grape', 'plum'];
default:
return [];
}
}
//test results
test(null); // []
test('yellow'); // ['banana', 'pineapple']
觀察可以發現程式碼重複性很高
重構成:
// 利用物件的方式來儲存資料,並用顏色當做 key 值
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function test(color) {
return fruitColor[color] || [];
}
Array.every
和 Array.some
來檢查 item檢查 fruits 中的所有水果是否都為紅色
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
let isAllRed = true;
// condition: 所有項目都必須為紅色
for (let f of fruits) {
if (!isAllRed) break;
isAllRed = (f.color == 'red');
}
console.log(isAllRed); // false
}
可以利用 Array.every
來重構成:
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
const isAllRed = fruits.every(f => f.color == 'red');
console.log(isAllRed); // false
}
如果要改成 是否有任一個紅色的水果存在,可以換用 Array.some
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// condition: 有任一個為紅色
const isAnyRed = fruits.some(f => f.color == 'red');
console.log(isAnyRed); // true
}