淺談JS如何寫出漂亮的條件表達(dá)式
多條件語句
多條件語句使用Array.includes
舉個(gè)例子
function printAnimals(animal) {
if (animal === "dog" || animal === "cat") {
console.log(`I have a ${animal}`);
}
}
console.log(printAnimals("dog")); // I have a dog
這種寫法在條件比較少的情況下看起來沒有問題,此時(shí)我們只有 2 種動(dòng)物,但是如果我們有更多的條件需要判斷(更多的動(dòng)物)呢?如果我們繼續(xù)拓展判斷的條件,那么代碼將會(huì)變得難以維護(hù),而且邏輯會(huì)不清晰。
解決方法
可以使用Array.includes來重寫條件語句
function printAnimals(animal) {
const animals = ["dog", "cat", "hamster", "turtle"];
if (animals.includes(animal)) {
console.log(`I have a ${animal}`);
}
}
console.log(printAnimals("hamster")); // I have a hamster
在這里,我們創(chuàng)建了一個(gè)動(dòng)物數(shù)組,以便將條件與代碼的其余部分分開提取?,F(xiàn)在,如果我們想要檢查任何其他動(dòng)物,我們需要做的就是添加一個(gè)新的數(shù)組項(xiàng)。
我們還可以在這個(gè)函數(shù)的范圍之外使用 animals 變量,以便在代碼的其他地方重用它。這是一種編寫更清晰、更容易理解和維護(hù)的代碼的方法。不是嗎?
多屬性對(duì)象
這是一個(gè)非常好的技巧來壓縮你的代碼,使它看起來更簡(jiǎn)潔。讓我們以前面的示例為例,添加更多的條件。如果這個(gè)動(dòng)物不是一個(gè)簡(jiǎn)單的字符串,而是一個(gè)具有某些屬性的對(duì)象呢?
所以現(xiàn)在的要求是:
- 如果沒有動(dòng)物,拋出一個(gè)錯(cuò)誤
- 打印動(dòng)物的類型
- 打印動(dòng)物的名字
- 打印動(dòng)物的性別
const printAnimalDetails = (animal) => {
let result; // declare a variable to store the final value
// condition 1: check if animal has a value
if (animal) {
// condition 2: check if animal has a type property
if (animal.type) {
// condition 3: check if animal has a name property
if (animal.name) {
// condition 4: check if animal has a gender property
if (animal.gender) {
result = `${animal.name} is a ${animal.gender} ${animal.type};`;
} else {
result = "No animal gender";
}
} else {
result = "No animal name";
}
} else {
result = "No animal type";
}
} else {
result = "No animal";
}
return result;
};
console.log(printAnimalDetails()); // 'No animal'
console.log(printAnimalDetails({ type: "dog", gender: "female" })); // 'No animal name'
console.log(printAnimalDetails({ type: "dog", name: "Lucy" })); // 'No animal gender'
console.log(
printAnimalDetails({ type: "dog", name: "Lucy", gender: "female" })
); // 'Lucy is a female dog'
上面的代碼它工作得很好,但是代碼很長(zhǎng),很難維護(hù)。如果不使用提示工具,可能會(huì)浪費(fèi)一些時(shí)間來確定右括號(hào)的位置。想象將會(huì)發(fā)生什么如果代碼更復(fù)雜的邏輯。很多if...else的語句!
我們可以使用三元操作符、&&條件等來重構(gòu)上面的函數(shù),但是讓我們使用多個(gè)返回語句來編寫更精確的代碼。
const printAnimalDetails = ({ type, name, gender } = {}) => {
if (!type) return "No animal type";
if (!name) return "No animal name";
if (!gender) return "No animal gender";
// Now in this line of code, we're sure that we have an animal with all //the three properties here.
return `${name} is a ${gender} ${type}`;
};
console.log(printAnimalDetails()); // 'No animal type'
console.log(printAnimalDetails({ type: dog })); // 'No animal name'
console.log(printAnimalDetails({ type: dog, gender: female })); // 'No animal name'
console.log(printAnimalDetails({ type: dog, name: "Lucy", gender: "female" })); // 'Lucy is a female dog'
在重構(gòu)版本中,還包括解構(gòu)和默認(rèn)參數(shù)。默認(rèn)參數(shù)確保如果我們將 undefined 作為參數(shù)傳遞給方法,我們?nèi)匀挥幸粋€(gè)要解構(gòu)的值,這里是一個(gè)空對(duì)象 {}。
通常,代碼是在這兩種方法之間編寫的。
舉個(gè)例子
function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"];
// condition 1: vegetable should be present
if (vegetable) {
// condition 2: must be one of the item from the list
if (vegetables.includes(vegetable)) {
console.log(`I like ${vegetable}`);
// condition 3: must be large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}
} else {
throw new Error("No vegetable from the list!");
}
}
printVegetablesWithQuantity(null); // No vegetable from the list!
printVegetablesWithQuantity("cabbage"); // I like cabbage
printVegetablesWithQuantity("cabbage", 20);
// 'I like cabbage`
// 'I have bought a large quantity'
現(xiàn)在,我們有:
- 過濾無效條件的 if/else 語句
- 3 層嵌套的 if 語句(條件 1、2 和 3)
- 一個(gè)通用的規(guī)則是當(dāng)發(fā)現(xiàn)無效條件時(shí)盡早返回。
function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"];
// condition 1: throw error early
if (!vegetable) throw new Error("No vegetable from the list!");
// condition 2: must be in the list
if (vegetables.includes(vegetable)) {
console.log(`I like ${vegetable}`);
// condition 3: must be a large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}
}
通過這樣做,我們減少了一個(gè)嵌套語句的級(jí)別。這種編碼風(fēng)格很好,特別是當(dāng)使用長(zhǎng)if語句時(shí)。通過反轉(zhuǎn)條件并提前返回,我們可以進(jìn)一步減少嵌套if。
請(qǐng)看下面的條件 2 是怎么做的:
function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"];
if (!vegetable) throw new Error("No vegetable from the list!");
// condition 1: throw error early
if (!vegetables.includes(vegetable)) return;
// condition 2: return from the function is the vegetable is not in
// the list
console.log(`I like ${vegetable}`);
// condition 3: must be a large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}
通過反轉(zhuǎn)條件 2 的條件,代碼不再具有嵌套語句。當(dāng)我們有很多條件并且希望在任何特定條件不滿足時(shí)停止進(jìn)一步的處理時(shí),這種技術(shù)是有用的。
因此,總是以減少嵌套和盡早返回為目標(biāo),但不要過度。
替換Switch語句
讓我們看一下下面的例子,我們想要根據(jù)顏色打印水果:
function printFruits(color) {
// use switch case to find fruits by color
switch (color) {
case "red":
return ["apple", "strawberry"];
case "yellow":
return ["banana", "pineapple"];
case "purple":
return ["grape", "plum"];
default:
return [];
}
}
printFruits(null); // []
printFruits("yellow"); // ['banana', 'pineapple']
上面的代碼實(shí)現(xiàn)沒有錯(cuò)誤,但是很冗長(zhǎng),同樣的結(jié)果可以使用更簡(jiǎn)潔的語法來實(shí)現(xiàn)。
// use object literal to find fruits by color
const fruitColor = {
red: ["apple", "strawberry"],
yellow: ["banana", "pineapple"],
purple: ["grape", "plum"],
};
function printFruits(color) {
return fruitColor[color] || [];
}
同樣的,也可以使用 Map 來實(shí)現(xiàn):
// use Map to find fruits by color
const fruitColor = new Map()
.set("red", ["apple", "strawberry"])
.set("yellow", ["banana", "pineapple"])
.set("purple", ["grape", "plum"]);
function printFruits(color) {
return fruitColor.get(color) || [];
}
Map是 ES5 以來可用的對(duì)象類型,它允許存 key-value。
對(duì)于上面的示例,可以使用 Array.filter 實(shí)現(xiàn)相同的結(jié)果。
const fruits = [
{ name: "apple", color: "red" },
{ name: "strawberry", color: "red" },
{ name: "banana", color: "yellow" },
{ name: "pineapple", color: "yellow" },
{ name: "grape", color: "purple" },
{ name: "plum", color: "purple" },
];
function printFruits(color) {
return fruits.filter((fruit) => fruit.color === color);
}
默認(rèn)參數(shù)與解構(gòu)
在使用 JavaScript 時(shí),我們總是需要檢查 null/undefined 并分配默認(rèn)值或編譯中斷。
function printVegetablesWithQuantity(vegetable, quantity = 1) {
// if quantity has no value, assign 1
if (!vegetable) return;
console.log(`We have ${quantity} ${vegetable}!`);
}
//results
}
printVegetablesWithQuantity('cabbage'); // We have 1 cabbage!
printVegetablesWithQuantity('potato', 2); // We have 2 potato!
如果蔬菜是一個(gè)對(duì)象呢?我們可以分配一個(gè)默認(rèn)參數(shù)嗎?
function printVegetableName(vegetable) {
if (vegetable && vegetable.name) {
console.log(vegetable.name);
} else {
console.log("unknown");
}
}
printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: "cabbage", quantity: 2 }); // cabbage
在上面的示例中,我們希望打印蔬菜名(如果它可用)或打印 unknown。
我們可以通過使用默認(rèn)參數(shù)&解構(gòu)來避免條件if (vegetable && vegetable.name){}。
// destructing - get name property only
// assign default empty object {}
function printVegetableName({ name } = {}) {
console.log(name || "unknown");
}
printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: "cabbage", quantity: 2 }); // cabbage
因?yàn)槲覀冎恍枰獙傩悦?,所以我們可以使?{name} 來改變參數(shù)的結(jié)構(gòu),然后我們可以在代碼中使用 name 作為變量,而不是使用 vegetable.name。
我們還將一個(gè)空對(duì)象 {} 賦值為默認(rèn)值,否則在執(zhí)行 printVegetableName(undefined) 時(shí),它將給出一個(gè)錯(cuò)誤—— Cannot destructure property name of undefined or null,因?yàn)樵?undefined 中沒有 name 屬性。
匹配所有或部分條件
我們可以通過使用這些Array方法來減少代碼行數(shù)。
下面的代碼,我們想要檢查是否所有的水果都是紅色的:
const fruits = [
{ name: "apple", color: "red" },
{ name: "banana", color: "yellow" },
{ name: "grape", color: "purple" },
];
function test() {
let isAllRed = true;
// condition: all fruits must be red
for (let f of fruits) {
if (!isAllRed) break;
isAllRed = f.color == "red";
}
console.log(isAllRed); // false
}
上面的代碼太過冗長(zhǎng),我們可以通過使用 Array.every 來減少代碼行:
const fruits = [
{ name: "apple", color: "red" },
{ name: "banana", color: "yellow" },
{ name: "grape", color: "purple" },
];
function test() {
// condition: short way, all fruits must be red
const isAllRed = fruits.every((f) => f.color == "red");
console.log(isAllRed); // false
}
同樣的,如果我們想要測(cè)試任何一個(gè)水果是否是紅色的,我們可以使用 Array.some:
const fruits = [
{ name: "apple", color: "red" },
{ name: "banana", color: "yellow" },
{ name: "grape", color: "purple" },
];
function test() {
// condition: if any fruit is red
const isAnyRed = fruits.some((f) => f.color == "red");
console.log(isAnyRed); // true
}
使用可選鏈和 Nullish 合并
這兩個(gè)功能對(duì)于 JavaScript 編寫更簡(jiǎn)潔的條件非常有用。在編寫本文時(shí),它們還沒有得到完全的支持,可能需要使用Babel進(jìn)行編譯。
可選鏈接能夠處理類似樹的結(jié)構(gòu),而不需要顯式地檢查中間節(jié)點(diǎn)是否存在,并且Nullish與可選鏈接結(jié)合使用非常有效,可以確保不存在節(jié)點(diǎn)的默認(rèn)值。
舉個(gè)例子:
const car = {
model: "Fiesta",
manufacturer: {
name: "Ford",
address: {
street: "Some Street Name",
number: "5555",
state: "USA",
},
},
};
// to get the car model
const model = (car && car.model) || "default model";
// to get the manufacturer street
const street =
(car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.address.street) ||
"default street";
// request an un-existing property
const phoneNumber =
car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.phoneNumber;
console.log(model); // 'Fiesta'
console.log(street); // 'Some Street Name'
console.log(phoneNumber); // undefined
因此,如果我們想打印出來,如果汽車制造商來自美國(guó),代碼應(yīng)該是這樣的:
const isManufacturerFromUSA = () => {
if (
car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.address.state === "USA"
) {
console.log("true");
}
};
checkCarManufacturerState(); // 'true'
可以清楚地看到,對(duì)于更復(fù)雜的對(duì)象結(jié)構(gòu),這會(huì)變得多么混亂。有一些第三方庫,如 lodash 或idx,它們有自己的功能。例如 lodash 有 _.get 方法。但是,在 JavaScript 語言本身中引入這個(gè)特性。
以下是這些新功能的工作原理:
// to get the car model
const model = car?.model ?? "default model";
// to get the manufacturer street
const street = car?.manufacturer?.address?.street ?? "default street";
// to check if the car manufacturer is from the USA
const isManufacturerFromUSA = () => {
if (car?.manufacturer?.address?.state === "USA") {
console.log("true");
}
};
目前在 Stage 3 階段。
以上就是基于JavaScript實(shí)現(xiàn)條件表達(dá)式的一些分享,希望對(duì)你能有所幫助~
以上就是淺談JS如何寫出漂亮的條件表達(dá)式的詳細(xì)內(nèi)容,更多關(guān)于JS如何寫出漂亮的條件表達(dá)式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS實(shí)現(xiàn)簡(jiǎn)易圖片輪播效果的方法
這篇文章主要介紹了JS實(shí)現(xiàn)簡(jiǎn)易圖片輪播效果的方法,實(shí)例分析了javascript操作圖片實(shí)現(xiàn)輪播特效的技巧,需要的朋友可以參考下2015-03-03
微信小程序button標(biāo)簽open-type屬性原理解析
這篇文章主要介紹了微信小程序button標(biāo)簽open-type屬性原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
JavaScript設(shè)計(jì)模式中的觀察者模式
這篇文章主要介紹了JavaScript設(shè)計(jì)模式中的觀察者模式,觀察者設(shè)計(jì)模式適用于監(jiān)聽一對(duì)多的操作,例如監(jiān)聽對(duì)象屬性的修改等等,觀察者模式能夠降低代碼耦合度,提升可擴(kuò)展性2022-06-06
js實(shí)現(xiàn)簡(jiǎn)潔大方的二級(jí)下拉菜單效果代碼
這篇文章主要介紹了js實(shí)現(xiàn)簡(jiǎn)潔大方的二級(jí)下拉菜單效果代碼,涉及javascript通過鼠標(biāo)事件控制頁面元素的動(dòng)態(tài)變換技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09

