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 规范定制中。
很快就能用上这爽到飞起的写法了!
让咱们学习并尝试新的技巧和技术,编写更干净,更可维护的代码。