How to avoid using too many if elses?

1. Introduction

I believe you have heard of callback hell – callback functions are nested layer by layer, which greatly reduces code readability. In fact, if-else is nested layer by layer, as shown in the figure below, which will also form a situation similar to callback hell.

When the business is more complex, there are many judgment conditions, and the project is in a hurry, it is especially easy to use too much if-else. It has many disadvantages, such as poor code readability, confusing code, high complexity, affecting development efficiency, high maintenance costs, etc.

Therefore, it is necessary to take some measures to avoid these problems when we code daily. The original intention of this article is not to suggest that you don’t use if-else at all, but to hope that we can code more elegantly after learning more solutions.

2. 8 optimization/alternative solutions for if-else

1. Use exclusion strategies[1]:!,!!

Logical NOT is a kind of logical operation, which refers to the inverse value of the original value.

When you want to write like this…

1. Determine whether it is empty
if(value === null || value === NaN || value === 0 || value === ''|| value === undefined )
{
…
}

2. Determine whether the array contains elements that meet a certain condition
const name = arr.find(item => item.status === 'error')?.name;
if(name !== undefined & amp; & amp; name !== ''){
…
}

You might as well try writing like this:

1. Determine whether it is empty
if(!value){……}

2. Determine whether the array contains elements that meet a certain condition
if(!!arr.find(item => item.status === 'error')?.name){……}

2. Use conditional (ternary) operator [2]: c ? t : f

Ternary operator: condition ? exprIfTrue : exprIfFalse; If the condition is true, the expression before the colon (:) is executed; if the condition is false, the last expression is executed.

When you want to write like this…

let beverage = '';
if(age > 20){
beverage = 'beer';
} else {
beverage = 'juice';
}

You might as well try writing like this:

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

tips: It is recommended to use only one level of ternary operator, as multiple levels of nesting will result in poor readability.

3. Use short-circuit operators: & amp; & amp;[3], ||[4]

  • & amp; & amp; is a false operation, judged from left to right, if a false value is encountered, a false value will be returned and will not be executed again, otherwise the last true value will be returned;

  • || is a truth operation, judged from left to right, if a true value is encountered, a true value will be returned and will not be executed again, otherwise the last false value will be returned.

When you want to write like this…

 if (isOnline){
    makeReservation(user);
    }

You might as well try writing like this:

 isOnline & amp; & amp; makeReservation(user);

4. Use switch statement[5]

When you want to write like this…

 let result;
    if (type === 'add'){
    result = a + b;
    } else if(type === 'subtract'){
    result = a - b;
    } else if(type === 'multiply'){
    result = a * b;
    } else if(type === 'divide'){
    result = a / b;
    } else {
    console.log('Calculation is not recognized');
    }

You might as well try writing like this:

let result;
switch (type) {
   case 'add':
     result = a + b;
     break;
   case 'subtract':
     result = a - b;
     break;
   case 'multiply':
     result = a * b;
     break;
   case 'divide':
     result = a / b;
     break;
   default:
    console.log('Calculation is not recognized');
}

Personally, I think that for this type of relatively simple judgment, using a switch statement will not reduce the amount of code, but it will make it clearer.

5. Define relevant functions to split logic and simplify the code

When you want to write like this…

function itemDropped(item, location) {
    if (!item) {
        return false;
    } else if (outOfBounds(location) {
        var error = outOfBounds;
        server.notify(item, error);
        items.resetAll();
        return false;
    } else {
        animateCanvas();
        server.notify(item, location);
        return true;
    }
}

You might as well try writing like this:

function itemDropped(item, location) {
  const dropOut = function () {
    server.notify(item, outOfBounds);
    items.resetAll();
    return false;
  };

  const dropIn = function () {
    animateCanvas();
    server.notify(item, location);
    return true;
  };

  return !!item & amp; & amp; (outOfBounds(location) ? dropOut() : dropIn());
}

Careful friends will find that in this example, the optimization solution mentioned above is also used. This shows that we can mix and match multiple solutions according to the actual situation when coding.

6. Define functions as objects and exhaustively search for corresponding processing methods

  • Define common objects

    For the example of Option 3, you might as well try writing this:

function calculate(action, num1, num2) {
  const actions = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
    multiply: (a, b) => a * b,
    divide: (a, b) => a / b,
  };
?
  return actions[action]?.(num1, num2)  "Calculation is not recognized";
}

  • Define Map object

    The key of an ordinary object needs to be a string, while the key of a Map[6] object can be an object, an array or more types, which is more flexible.

let statusMap = new Map([
  [
    { role: "worker", status: "1" },
    () => { },
  ],
  [
    { role: "worker", status: "2" },
    () => { },
  ],
  [
    { role: "boss lady", status: "1" },
    () => { },
  ],
]);

let getStatus = function (role, status) {
  statusMap.forEach((value, key) => {
    if (JSON.stringify(key) === JSON.stringify({ role, status })) {
      value();
    }
  });
};

getStatus("worker", "1");

tips: JSON.stringify()[7] can be used for deep comparison/deep copy.

7. Use the chain of responsibility model[8]

Chain of Responsibility Mode: Rewrite the entire processing logic into a responsibility delivery chain, and the request is passed on this chain until an object handles the request.

For example, event bubbling in JS.

Simply put, _event bubbling_ is to bind an event on an object. If an event handler is defined, the handler will be called. On the contrary, if it is not defined, this event will be propagated to the parent of the object until the event is executed, and finally reaches the outermost layer, the document object.

This means that in this mode there is always a program handling the event.

Another example, when you want to write like this…

function demo (a, b, c) {
  if (f(a, b, c)) {
    if (g(a, b, c)) {
      
    }
    
    else if (h(a, b, c)) {
      
    }
    
  } else if (j(a, b, c)) {
    
  } else if (k(a, b, c)) {
    
  }
}

You might as well refer to this way of writing:

const rules = [
  {
    match: function (a, b, c) { },
    action: function (a, b, c) { }
  },
  {
    match: function (a, b, c) { },
    action: function (a, b, c) { }
  },
  {
    match: function (a, b, c) { },
    action: function (a, b, c) { }
  }
  
]


function demo (a, b, c) {
  for (let i = 0; i < rules.length; i + + ) {
    if (rules[i].match(a, b, c)) {
      return rules[i].action(a, b, c)
    }
  }
}

Extended topic-How to reduce the complexity of if else code?

Related article reading: How to painlessly reduce the complexity of if else noodle code [9] It is recommended to read it several times! ! !

8. Strategy pattern + factory method

Because this method is relatively complex, this article will not introduce it in detail for the time being.

For details, please refer to the article Optimization Plan 8 Eight plans for if-else code optimization [10].

3. Summary

This article roughly introduces 8 methods of optimizing/replacing if-else. I hope it can bring some inspiration to your daily coding.

As mentioned at the beginning, our goal is not to eliminate if-else in the code, but to allow us to learn more solutions and choose a better coding method according to the actual situation. Therefore, when you find that there are a lot of if-else in your code or when you want to use if-else, you might as well stop and think about it– How can we write more elegantly and make it easier to maintain in the future?

4. Reference and thanks

  1. Optimize excessive use of IF statements in JS[11]

  2. Short-circuit operators (logical AND & amp; & amp; and logical OR ||)[12]

  3. How to optimize multiple if-else judgments[13]

  4. Eight solutions for if-else code optimization[14]

  5. How to replace if-else and switch in the project[15]

  6. How to painlessly reduce the complexity of if else noodle code[16]