{ },],_if else if else if 如何减少复杂度">
当前位置:   article > 正文

如何避免使用过多的 if else?_if else if else if 如何减少复杂度

if else if else if 如何减少复杂度

一、引言

相信大家听说过回调地狱——回调函数层层嵌套,极大降低代码可读性。其实,if-else层层嵌套,如下图所示,也会形成类似回调地狱的情况。

当业务比较复杂,判断条件比较多,项目进度比较赶时,特别容易使用过多if-else。其弊端挺多的,如代码可读性差、代码混乱、复杂度高、影响开发效率、维护成本高等。

因此,我们在日常编码时,有必要采取一些措施避免这些问题。本文的初衷不是建议大家完全不用if-else,而是希望我们能够在学会更多解决方案后更优雅地编码。


二、8种if-else的优化/替代方案

1. 使用排非策略[1]:!、!!

逻辑非(logic NOT),是逻辑运算中的一种,就是指本来值的反值。

当你想这么写时……

  1. 1、判断是否为空
  2. if(value === null || value === NaN || value === 0 || value === ''|| value === undefined   )
  3. {
  4. ……
  5. }
  6. 2、判断是否数组是否含有符合某条件的元素
  7. const name = arr.find(item => item.status === 'error')?.name;
  8. if(name !== undefined && name !== ''){
  9. ……
  10. }

不妨尝试这么写:

  1. 1、判断是否为空
  2. if(!value){……}
  3. 2、判断是否数组是否含有符合某条件的元素
  4. if(!!arr.find(item => item.status === 'error')?.name){……}

2. 使用条件(三元)运算符[2]: c ? t : f

三元运算符: condition ? exprIfTrue : exprIfFalse; 如果条件为真值,则执行冒号(:)前的表达式;若条件为假值,则执行最后的表达式。

当你想这么写时……

  1. let beverage = '';
  2. if(age > 20){
  3. beverage = 'beer';
  4. else {
  5. beverage = 'juice';
  6. }

不妨尝试这么写:

  1. const beverage = age > 20 ? 'beer' : 'juice';

tips: 建议只用一层三元运算符,多层嵌套可读性差。


3. 使用短路运算符:&&[3]、 ||[4]

  • && 为取假运算,从左到右依次判断,如果遇到一个假值,就返回假值,以后不再执行,否则返回最后一个真值;

  • || 为取真运算,从左到右依次判断,如果遇到一个真值,就返回真值,以后不再执行,否则返回最后一个假值。

当你想这么写时……

  1.     if (isOnline){
  2.     makeReservation(user);
  3.     }

不妨尝试这么写:

  1.  isOnline && makeReservation(user);

4. 使用 switch 语句[5]

当你想这么写时……

  1.     let result;
  2.     if (type === 'add'){
  3.     result = a + b;
  4.     } else if(type === 'subtract'){
  5.     result = a - b;
  6.     } else if(type === 'multiply'){
  7.     result = a * b;
  8.     } else if(type === 'divide'){
  9.     result = a / b;
  10.     } else {
  11.     console.log('Calculation is not recognized');
  12.     }

不妨尝试这么写:

  1. let result;
  2. switch (type) {
  3.    case 'add':
  4.      result = a + b;
  5.      break;
  6.    case 'subtract':
  7.      result = a - b;
  8.      break;
  9.    case 'multiply':
  10.      result = a * b;
  11.      break;
  12.    case 'divide':
  13.      result = a / b;
  14.      break;
  15.    default:
  16.     console.log('Calculation is not recognized');
  17. }

个人认为,对于这类比较简单的判断,用switch语句虽然不会减少代码量,但是会更清晰喔。


5. 定义相关函数拆分逻辑,简化代码

当你想这么写时……

  1. function itemDropped(item, location) {
  2.     if (!item) {
  3.         return false;
  4.     } else if (outOfBounds(location) {
  5.         var error = outOfBounds;
  6.         server.notify(item, error);
  7.         items.resetAll();
  8.         return false;
  9.     } else {
  10.         animateCanvas();
  11.         server.notify(item, location);
  12.         return true;
  13.     }
  14. }

不妨尝试这么写:

  1. function itemDropped(item, location) {
  2.   const dropOut = function () {
  3.     server.notify(item, outOfBounds);
  4.     items.resetAll();
  5.     return false;
  6.   };
  7.   const dropIn = function () {
  8.     animateCanvas();
  9.     server.notify(item, location);
  10.     return true;
  11.   };
  12.   return !!item && (outOfBounds(location) ? dropOut() : dropIn());
  13. }

细心的朋友会发现,在这个例子中,同时使用了前文提及的优化方案。这说明我们在编码时可以根据实际情况混合使用多种解决方案。


6. 将函数定义为对象,通过穷举查找对应的处理方法

  • 定义普通对象

    对于方案3的例子,不妨尝试这么写:

  1. function calculate(action, num1, num2) {
  2.   const actions = {
  3.     add: (a, b) => a + b,
  4.     subtract: (a, b) => a - b,
  5.     multiply: (a, b) => a * b,
  6.     divide: (a, b) => a / b,
  7.   };
  8.   return actions[action]?.(num1, num2) ?? "Calculation is not recognized";
  9. }
  • 定义 Map 对象

    普通对象的键需要是字符串,而 Map[6] 对象的键可以是一个对象、数组或者更多类型,更加灵活。

  1. let statusMap = new Map([
  2.   [
  3.     { role: "打工人"status"1" },
  4.     () => { },
  5.   ],
  6.   [
  7.     { role: "打工人"status"2" },
  8.     () => { },
  9.   ],
  10.   [
  11.     { role: "老板娘"status"1" },
  12.     () => { },
  13.   ],
  14. ]);
  15. let getStatus = function (role, status) {
  16.   statusMap.forEach((valuekey=> {
  17.     if (JSON.stringify(key=== JSON.stringify({ role, status })) {
  18.       value();
  19.     }
  20.   });
  21. };
  22. getStatus("打工人""1"); 

tips: JSON.stringify()[7]可用于深比较/深拷贝。


7. 使用责任链模式[8]

责任链模式:将整个处理的逻辑改写成一条责任传递链,请求在这条链上传递,直到有一个对象处理这个请求。

例如 JS 中的_事件冒泡_。

简单来说,_事件冒泡_就是在一个对象上绑定事件,如果定义了事件的处理程序,就会调用处理程序。相反没有定义的话,这个事件会向对象的父级传播,直到事件被执行,最后到达最外层,document对象上。

这意味着,在这种模式下,总会有程序处理该事件。

再举个

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/377880
推荐阅读
相关标签