1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
      <output id="hzk7v"></output>
    2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
    3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

      详解写好JS条件语句的5条守则

       更新时间£º2019年02月28日 09:04:28   作者£ºecelyn Yeen(@jecelynyeen)   我要评论

      这篇文章主要介绍了详解写好JS条件语句的5条守则£¬小编觉得挺不错的£¬现在分享给大家£¬也给大家做个参考¡£一起跟随小编过来看看吧

      在用 JavaScript 工作时£¬我们经常和条件语句打交道£¬这里有5条让你写出更好/干净的条件语句的建议¡£

      目录£º

      1.多重判断时使用 Array.includes

      2.更少的嵌套£¬尽早 return

      3.使用默认参数和解构

      4.倾向于遍历对象而不是 Switch 语句

      5.对 所有/部分 判断使用 Array.every & Array.some

      6.总结

      1.多重判断时使用 Array.includes

      让我们看一下下面这个例子:

      // condition
      function test(fruit) {
       if (fruit == 'apple' || fruit == 'strawberry') {
        console.log('red');
       }
      }
      
      

      第一眼£¬上面这个例子看起来没问题¡£如果我们有更多名字叫 cherry 和 cranberries 的红色水果呢£¿我们准备用更多的 || 来拓展条件语句吗£¿

      我们可以用 Array.includes (Array.includes)重写条件语句¡£

      function test(fruit) {
       const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
       if (redFruits.includes(fruit)) {
        console.log('red');
       }
      }
      
      

      我们把红色的水果(red fruits)这一判断条件提取到一个数组¡£这样一来£¬代码看起来更整洁¡£

      2.更少的嵌套£¬尽早 Return

      让我们拓展上一个例子让它包含两个条件¡£

      • 如果没?#20889;?#20837;参数 fruit£¬抛出错误
      • 接受 quantity 参数£¬并且在 quantity 大于 10 时打印出来
      function test(fruit, quantity) {
       const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
       // 条件 1: fruit 必须有值
       if (fruit) {
        // 条件 2: 必须是red的
        if (redFruits.includes(fruit)) {
         console.log('red');
      
         // 条件 3: quantity大于10
         if (quantity > 10) {
          console.log('big quantity');
         }
        }
       } else {
        throw new Error('No fruit!');
       }
      }
      
      // 测试结果
      test(null); // error: No fruits
      test('apple'); // print: red
      test('apple', 20); // print: red, big quantity

      在上面的代码, 我们有:

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

      我个人遵循的规则一般是在发现无效条件时£¬尽早Return¡£

      /_ 当发现无效语句时£¬尽早Return _/
      
      function test(fruit, quantity) {
       const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
       // 条件 1: 尽早抛出错误
       if (!fruit) throw new Error('No fruit!');
      
       // 条件 2: 必须是红色的
       if (redFruits.includes(fruit)) {
        console.log('red');
      
        // 条件 3: 必须是大质量的
        if (quantity > 10) {
         console.log('big quantity');
        }
       }
      }

      这样一来£¬我?#24039;?#20102;一层嵌套语句¡£这种编码风格非常好£¬尤其是当你有很长的if语句的时候(想象你需要滚动到最底层才知道还有else语句£¬这并不酷)

      我们可以通过 倒置判断条件 & 尽早return 进一步减少if嵌套¡£看下面我们是怎么处理判断 条件2 的:

      /_ 当发现无效语句时£¬尽早Return _/
      
      function test(fruit, quantity) {
       const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
       // 条件 1: 尽早抛出错误
       if (!fruit) throw new Error('No fruit!');
       // 条件 2: 当水果不是红色时停止继续执行
       if (!redFruits.includes(fruit)) return; 
      
       console.log('red');
      
       // 条件 3: 必须是大质量的
       if (quantity > 10) {
        console.log('big quantity');
       }
      }
      
      

      通过倒置判断条件2£¬我们的代码避免了嵌套语句¡£这个技巧在我们需要进行很长的逻辑判断时是非常有用的£¬特别是我们希望能够在条件不满足时能够停止下来进?#20889;?#29702;¡£

      而且这么做并不困?#36873;?#38382;?#39318;?#24049;£¬这个版本(没有嵌套)是不是比之前的(两层条件嵌套)更好£¬可读性更高£¿

      但对于我£¬?#19968;?#20445;留先前的版本(包含两层嵌套)¡£这是因为:

      • 代码比较短且直接£¬包含if嵌套的更清晰
      • 倒置判断条件可能加重思考的负担(增?#23588;现?#36733;荷)

      因此£¬应?#26412;?#21147;减少嵌套和尽早return£¬但不要过?#21462;?#22914;果你?#34892;?#36259;的话£¬可以看一下关于这个话题的一篇文章和 StackOverflow 上的讨论¡£

      • Avoid Else, Return Early by Tim Oxley
      • StackOverflow discussion on if/else coding style

      3.使用默认参数和解构

      ?#20063;?#19979;面的代码你可能会熟悉£¬在JavaScript中我们总是需要检查 null / undefined的值和指定默?#29616;?

      function test(fruit, quantity) {
       if (!fruit) return;
       // 如果 quantity 参数没?#20889;?#20837;£¬设置默?#29616;?#20026; 1
       const q = quantity || 1; 
      
       console.log(`We have ${q} ${fruit}!`);
      }
      
      //test results
      test('banana'); // We have 1 banana!
      test('apple', 2); // We have 2 apple!
      
      

      ?#23548;?#19978;£¬我们可以通过声明 默认函数参数 来消除变量 q¡£

      function test(fruit, quantity = 1) {
       // 如果 quantity 参数没?#20889;?#20837;£¬设置默?#29616;?#20026; 1
       if (!fruit) return;
       console.log(`We have ${quantity} ${fruit}!`);
      }
      
      //test results
      test('banana'); // We have 1 banana!
      test('apple', 2); // We have 2 apple!
      
      

      这更加直观£¬不是吗£¿注意£¬每个声明都有自己的默认参数.

      例如£¬我们也能给fruit分配默?#29616;?function test(fruit = 'unknown', quantity = 1)¡£

      如果fruit是一个object会怎么样£¿我们能分配一个默认参数吗£¿

      function test(fruit) { 
       // 当值存在时打印 fruit 的值
       if (fruit && fruit.name) {
        console.log (fruit.name);
       } else {
        console.log('unknown');
       }
      }
      
      //test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      
      

      看上面这个例子£¬我们想打印 fruit 对象中可能存在的 name 属性¡£否则我们将打印unknown¡£我们可以通过默认参数以及解构从而避免判断条件 fruit && fruit.name

      // 解构 - 仅仅获取 name 属性
      // 为其赋默?#29616;?#20026;空对象
      function test({name} = {}) {
       console.log (name || 'unknown');
      }
      
      // test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      
      

      由于我们只需要 name 属性£¬我们可以用 {name} 解构出参数£¬然后我们就能使用变量 name 代替 fruit.name¡£

      我们也需要声明空对象 {} 作为默?#29616;µ¡?#22914;果我们不这么做£¬当执行 test(undefined) 时£¬你将得到一个无法对 undefined 或 null 解构的的错误¡£因为在 undefined 中没有 name 属性¡£

      如果你不介意使用第三方库£¬这有一些方式减少null的检查:

      • 使用 Lodash get函数
      • 使用Facebook开源的idx库(with Babeljs)

      这是一个使用Lodash的例子:

      function test(fruit) {
       // 获取属性名£¬如果属性名不可用£¬赋默?#29616;?#20026; unknown
       console.log(__.get(fruit, 'name', 'unknown'); 
      }
      
      // test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      
      

      你可以在jsbin运行demo代码¡£除此之外£¬如果你是函数式编程的粉丝£¬你可能选择使用 Lodash fp£¬Lodash的函数式版本(方法变更为get或者getOr)¡£

      4.倾向于对象遍历而不是Switch语句

      让我们看下面这个例子£¬我们想根据 color 打印出水果:

      function test(color) {
       // 使用条件语句来寻找对应颜色的水果
       switch (color) {
        case 'red':
         return ['apple', 'strawberry'];
        case 'yellow':
         return ['banana', 'pineapple'];
        case 'purple':
         return ['grape', 'plum'];
        default:
         return [];
       }
      }
      
      // test results
      test(null); // []
      test('yellow'); // ['banana', 'pineapple']

      上面的代码看起来没?#20889;?#35823;£¬但是我找到了一些累赘¡£用对象遍历实现相同的结果£¬语法看起来更简洁:

      const fruitColor = {
       red: ['apple', 'strawberry'],
       yellow: ['banana', 'pineapple'],
       purple: ['grape', 'plum']
      };
      
      function test(color) {
       return fruitColor[color] || [];
      }
      
      

      或者你也可以使用 Map实现相同的结果:

       const fruitColor = new Map()
        .set('red', ['apple', 'strawberry'])
        .set('yellow', ['banana', 'pineapple'])
        .set('purple', ['grape', 'plum']);
      
      function test(color) {
       return fruitColor.get(color) || [];
      }
      
      

      Map是一种在 ES2015 规范之后实现的对象类?#20572;?#20801;许你存储 key 和 value 的值¡£

      但我们是否应当禁止switch语句的使用呢?#30475;?#26696;是不要限制你自己¡£从个人来?#25285;¬Î一?#23613;可能的使用对象遍历£¬但?#20063;?#19981;严格遵守它£¬而是使用对当前的场景更有意义的方式¡£

      Todd Motto有一篇关于 switch 语句对比对象遍历的更深入的文章£¬你可以在这个地方阅读

      TL;DR; 重构语法

      在上面的例子£¬我们能够用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) {
       return fruits.filter(f => f.color == color);
      }
      
      

      有着不止一种方法能够实现相同的结果£¬我们以上展示了 4 种¡£

      5.对 所有/部分 判断使用Array.every & Array.some

      这最后一个建议更多是关于利用 JavaScript Array 的内置方法来减少代码行数¡£看下面的代码£¬我们想要检查是否所有水果都是红色:

      const fruits = [
        { name: 'apple', color: 'red' },
        { name: 'banana', color: 'yellow' },
        { name: 'grape', color: 'purple' }
       ];
      
      function test() {
       let isAllRed = true;
      
       // 条件£º所有水果都是红色
       for (let f of fruits) {
        if (!isAllRed) break;
        isAllRed = (f.color == 'red');
       }
      
       console.log(isAllRed); // false
      }
      
      

      代码那么长£¡我们可以通过 Array.every减少代码行数:

      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 一?#20889;?#30721;实现¡£

      const fruits = [
        { name: 'apple', color: 'red' },
        { name: 'banana', color: 'yellow' },
        { name: 'grape', color: 'purple' }
      ];
      
      function test() {
       // 条件£º任何一个水果是红色
       const isAnyRed = fruits.some(f => f.color == 'red');
      
       console.log(isAnyRed); // true
      }
      
      

      6.总结

      让我们一起生产更多可读性高的代码¡£我希望你能从这篇文章学到东西¡£也希望大家多多支持脚本之家¡£

      相关文章

      最新评论

      3dÊÔ»úºÅÖвÊÍø

        1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
          <output id="hzk7v"></output>
        2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
        3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

            1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
              <output id="hzk7v"></output>
            2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
            3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>