Array.includes
運用// bad example
function printAnimals(animal) {
if (animal === 'dog' || animal === 'cat') {
console.log(`I have a ${animal}`);
}
}
console.log(printAnimals('dog')); // I have a dog
複製代碼
上面的代碼看起來不錯,由於咱們只有兩個動物要檢查。可是,咱們不肯定用戶輸入。若是咱們還有其餘動物怎麼辦?若是咱們繼續用更多的OR
語句來擴展該語句,則代碼將變得更難維護,而不是那麼幹淨。javascript
解:java
咱們可使用重寫上面的條件 Array.includes
數組
// good example
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
複製代碼
return
// bad example
const printAnimalDetails = animal => {
let result;
// 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'
複製代碼
它工做正常,可是代碼又長又難以維護。維護代碼的時候可能會浪費一些時間弄清楚右括號在哪裏。bash
想象一下,若是代碼具備更復雜的邏輯,將會發生什麼 —— 不少 if .. else
app
咱們可使用三元運算符&&
條件等來重構上述函數,但讓咱們使用多個return語句編寫更精確的代碼。函數
// good example
const printAnimalDetails = ({ type, name, gender } = {}) => {
if (!type) return 'No animal type';
if (!name) return 'No animal name';
if (!gender) return 'No animal gender';
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'
複製代碼
另外一個例子:學習
// bad example
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
複製代碼
上面例子有如下問題測試
解:ui
發現無效條件時儘快返回spa
// good
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');
}
}
}
複製代碼
// bad example
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']
複製代碼
上面的代碼沒有錯,可是仍然很冗長。
使用object映射更簡潔的語法能夠實現相同的結果:
// good example
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function printFruits(color) {
return fruitColor[color] || [];
}
// 或者使用 Map,Map 是自 ES2015 起可用的對象類型
const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);
function printFruits(color) {
return fruitColor.get(color) || [];
}
// 或者使用 Array.filter,同樣能夠實現
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);
}
複製代碼
使用JavaScript時,咱們老是須要檢查 null
/ undefined
值並賦值,不然編譯會中斷。
// bad example
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
複製代碼
解:
經過使用默認參數和結構來避免煩人的判斷條件
// good example
function printVegetableName({ name } = {}) {
console.log(name || 'unknown');
}
printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: 'cabbage', quantity: 2 }); // cabbage
複製代碼
Array.every
和Array.some
等新語法糖// bad example
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
}
複製代碼
代碼太長了!咱們能夠減小行數,使用Array.every
:
// good example
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() {
const isAllRed = fruits.some(f => f.color == 'red');
console.log(isAnyRed); // 包含紅色:true
}
複製代碼
更多數組語法可查看 MDN Javascript Array Docs,不一一展開。
彩蛋
看看下面代碼,你必定有過這樣的煩惱,特別是接口過來鬼知道怎樣的數據。
const car = {
model: 'Fiesta',
manufacturer: {
name: 'Ford',
address: {
street: 'Some Street Name',
number: '5555',
state: 'USA'
}
}
}
const model = car && car.model || 'default model';
const street = car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.street || 'default street';
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
const isManufacturerFromUSA = () => {
if (car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.state === 'USA') {
console.log('true');
}
}
const isManufacturerFromUSA = () => {
if (car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.state === 'USA') {
console.log('true');
}
}
checkCarManufacturerState() // 'true'
複製代碼
您能夠清楚地看到,在對象結構複雜且不受控的狀況下,這會變得多麼混亂。
有一些第三方庫,例如lodash或idx具備本身的功能。例如lodash有_.get方法。
可是,JavaScript語言自己引入的此功能很是酷。
這些新功能的工做方式以下:
const model = car ?.model ?? 'default model';
const street = car ?.manufacturer ?.address ?.street ?? 'default street';
const isManufacturerFromUSA = () => {
if (car ?.manufacturer ?.address ?.state === 'USA') {
console.log('true');
}
}
複製代碼
這看起來更漂亮,更易於維護。它已經在 TC39 stage 3 規範定製中。
很快就能用上這爽到飛起的寫法了!
讓咱們學習並嘗試新的技巧和技術,編寫更乾淨,更可維護的代碼。