5个javascript小技巧让你写出更优雅的代码

在使用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.少写嵌套,尽早返回
让我们为之前之前的例子加两个条件

  • 如果没有提供水果,抛出错误
  • 如果该水果的数量大于10,将其打印出来
    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

让我们仔细看看上面的代码,我们有:

  • 1个if/else语句来筛选无效的条件
  • 3层if语句嵌套(条件1,2&3)

就我个人而言,我遵循一个总的规则是当发现无效条件时尽早返回

    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有嵌套).原因在于:

  • 这样的代码比较简洁和直白,一个嵌套的if使得结构更加清晰.
  • 条件反转会导致更多的思考过程(增加认知负担).

因此,始终追求更少的嵌套,更早地返回,但是不要过度.

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)

  • 使用lodash get函数
  • 使用Facebook开源的idx库(需要搭配Babeljs)

这里有一个使用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
    }

总结
让我们一起写出可读性更高的代码吧,希望这篇文章能够给你们带来一些启发和帮助

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值