在使用JavaScript时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净,漂亮的条件语句
1.使用array.includes来处理多重条件
举个栗子:
//条件语句
function test(fruit){
if(fruit == 'apple' || fruit == 'strawberry'){
console.log('red);
}
}
乍一看,这么写似乎没什么大问题.然而,如果我们想要匹配更多的红色水果呢,比如说樱桃或者蔓越莓?我们是不是得用更多的||来扩展这条语句?
我们可以使用Array.includes重写以上条件语句
function test(fruit){
// 条件提取到数组中
const redFruits = [''apples'',''strawberry',''cherry'',''cranberries''];
if(redFruits.includes(fruit)){
console.log(red)
}
}
我们把红色水果(条件)都提取到一个数组中,这使得我们的代码看齐俩更加整洁.
2.少写嵌套,尽早返回
让我们为之前之前的例子加两个条件
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:fruit 必须有值
if (fruit) {
// 条件 2: 必须为红色
if (redFruits.includes(fruit)) {
console.log('red');
}
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity')
}
} else {
throwError('No fruit');
}
}
// 测试结果
test(null) //报错:No fruits
test('apple') // 打印red
test('apple',20) 打印red big quantity
让我们仔细看看上面的代码,我们有:
就我个人而言,我遵循一个总的规则是当发现无效条件时尽早返回
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:fruit 必须有值
if (!fruit) throwError('No fruit');
// 条件 2: 必须为红色
if (redFruits.includes(fruit)) {
console.log('red');
}
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity')
}
}
如此一来,我们就少写一层嵌套,这是种很好的代码风格,尤其是在if语句很长的时候(试想一下,你得滚动到底部才知道那儿还有else语句,是不是有点不爽).
如果反转一下条件, 我们还可以进一步地减少嵌套层级.注意观察下面的条件2语句,看看是如何做到这点的:
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:fruit 必须有值
if (!fruit) throwError('No fruit');
// 条件 2: 必须为红色
if (!redFruits.includes(fruit)) return
console.log('red');
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity')
}
}
通过反转条件2,现在我们的代码已经没有嵌套了,当我们代码逻辑链很长,并且希望当某个条件不满足时再执行之后流程时,这个技巧会很好用.
然而,并没有任何硬性条件规则要求你这么做.这取决于你自己,对你而言,这个版本的代码(没有嵌套)是否要比那个版本(条件2有嵌套)的更好,可读性更强?
是我的话,我会选择前一个版本(条件2有嵌套).原因在于:
因此,始终追求更少的嵌套,更早地返回,但是不要过度.
3. 使用函数默认参数和解构
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (!fruit) return
const q = quantity || 1
console.log(`we have ${q}${fruit}`
}
// 测试结果
test('banana'); // we have 1 banana!
test('banana',2) // we have 2 banana!
事实上,我们可以通过函数的默认参数来去掉变量q
function test(fruit, quantity=1) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (!fruit) return
console.log(`we have ${quantity}${fruit}`
}
// 测试结果
test('banana'); // we have 1 banana!
test('banana',2) // we have 2 banana!
是不是更加简单、直白了?请注意,所有的函数参数都可以有其默认值,举例来说,我们同样可以为fruit赋予一个默认值:function test(fruit=‘unknown’,quantity=1).
那么如果fruit是一个对象(Object)呢?我们还可以使用默认参数吗?
function test(fruit) {
//果有值,则打印出来
if (fruit && fruit.name) {
console.log(fruit.name);
} else {
console.log('unknown');
}
}
// 测试结果
test(undefined) // unknown
test({}) // unknown
test({ name: 'apple', color: 'red' }) // apple
观察上面的例子,当水果名称属性存在时,我们希望将其打印出来,否则打印unknown 我们可以通过默认参数和解构赋值的方法来避免写出fruit && fruit.name这种条件
// 解构 只得到name属性
// 默认参数为空对象 {}
function test({ name } = {}) {
console.log(name || 'unknown');
}
// 测试结果
test(undefined) // unknown
test({}) // unknown
test({ name: 'apple', color: 'red' }) // apple
既然我们只需要fruit的name属性,我们可以使用{name}来将其解构出来,之后我们就可以在代码中使用name变量来取代fruit.name
我们还使用{}作为默认值
如果我们不这么做的话,在执行test(undefined)时,你回得到一个错误 Cannot destructrue property name of ‘undefined’ or null’,因为undefined上并没有name 属性
如果你不介意使用第三方库,有一些方法可以帮助减少空值检查(null)
这里有一个使用Loadsh的例子:
// 使用laodsh库提供的_方法
function test(fruit){
console.log(_.get(fruit,'name','unknown'') // 获取属性name的值,如果没有,设为默认值unknown
}
// 测试结果
test(undefined) // unknown
test({}) // unknown
test({ name: 'apple', color: 'red' }) // apple
你可以在这里运行代码演示.另外,如果你偏爱函数式变成(Fp),你可以选择使用Lodash fp-函数式版本的Lodash(方法名变为get或getOr)
4. 相较于switch,Map/Object也许是更好的选择
让我们看看下面的例子,我们想要根据颜色打印出各种水果
function test(color){
// 使用switch case来找到对应颜色的水果
switch (color) {
case 'red':
return ['apple','strawberry'];
break;
case 'yellow':
return ['banana','pineapple'];
break;
case 'purple':
return ['grape','plum'];
break;
default:
return [];
}
}
test(null)
test('yellow') // ['banana','pineapple'];
上面的代码看上去并没有错,但是就我个人而言,它看上去很冗长.同样的结果可以通过对象字面量来实现,语法也更加简洁
const fruitColor = {
red:['apple','strawberry'],
yellow:['banana','pineapple'],
red:['grape','plum'],
}
function test(color){
return fruitColor[color] || []
}
或者你也可以使用Map来实现同样的效果
// 使用Map来找到对应颜色的水果
const fruitColor = Map()
.set('red',['apple','strawberry'])
.set('yellow':['banana','pineapple'])
.set('red':['grape','plum']);
function test(color){
return fruitColor.get(color) || [];
}
Map是ES2015引入的新的对象类型,允许你存放键值对.
懒人版:重构语法
就以上的例子,事实上我们可以通过重构我们的代码,使用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 test(color){
// 通过filter来找到对应颜色的水果
return fruits.filter(f => f.color == color);
}
5. 使用Array.every和Array.some来处理全部/部分满足条件
最后一个小技巧更多地是关于使用新的(也不是很新了)javascript数组函数来减少代码行数.观察以下的代码,我们想要检查是否所有的水果都是红色:
const fruit = [
{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 test(){
let isAllRed = true;
// 条件 所有的水果都必须是红色
for (let f of fruits){
if(!isAllRed) return;
isAllRed = (f.color =='red');
}
console.log(isAllRed) // false
}
这段代码也太长了 我们可以通过Array.every来缩减代码
const fruit = [
{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 test(){
// 条件: 所有的水果都必须是红色的
const isAllRed = fruits.every(f=>f.color =='red');
console.log(isAllRed) // fasle
}
清晰多了对吧?类似的,如果我们想要检查是否至少有一个水果是红色的,我们可以使用Array.some仅用一行代码就可以实现出来
const fruit = [
{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 test(){
// 条件: 至少一个水果是红色的
const isAllRed = fruits.some(f=>f.color =='red');
console.log(isAllRed) // true
}
总结
让我们一起写出可读性更高的代码吧,希望这篇文章能够给你们带来一些启发和帮助