How to Optimize Complex Conditional Logic in JavaScript

Time: Column:Mobile & Frontend views:255

To combine two conditions into a single string, use this concatenated condition string as the key and the corresponding handler function as the value. You can then look up and execute the function using a Map object. This method is especially useful when dealing with multiple conditional checks. 

When writing JavaScript code, we often encounter situations where logical conditions become complex. Typically, we use if/else or switch statements to handle multiple conditions.

However, this approach has a drawback: as the complexity of the logic increases, the if/else or switch statements can become bloated and harder to understand. So how can we write conditional logic in a more elegant way?

Let’s explore this issue today!

Unary Conditional Logic

const onButtonClick = (status) => {
  if (status == 1) {
    jumpTo('Enter index page');
  } else if (status == 2) {
    jumpTo('Enter failure page');
  } else if (status == 3) {
    jumpTo('Enter failure page');
  } else if (status == 4) {
    jumpTo('Enter success page');
  } else if (status == 5) {
    jumpTo('Enter cancel page');
  } else {
    jumpTo('Other actions');
  }
}

From this code, we can see the button click logic: depending on the activity status, different pages are navigated to.

Of course, the above code can also be rewritten using switch:

const onButtonClick = (status) => {
  switch (status) {
    case 1:
      console.log('Enter index page');
      break;
    case 2:
    case 3:
      jumpTo('Enter failure page');
      break;
    case 4:
      jumpTo('Enter success page');
      break;
    case 5:
      jumpTo('Enter cancel page');
      break;
    default:
      jumpTo('Other actions');
      break;
  }
}

This looks much clearer than using if/else. Also, when the logic for case 2 and case 3 is the same, we can omit the execution statement and break, so that case 2 will automatically execute the logic of case 3.

However, the code is still not “perfect.” It can be further optimized:

const actions = {
  '1': ['Enter index page'],
  '2': ['Enter failure page'],
  '3': ['Enter failure page'],
  '4': ['Enter success page'],
  '5': ['Enter cancel page'],
  'default': ['Other actions'],
}
const onButtonClick = (status) => {
  let action = actions[status] || actions['default'];
  jumpTo(action[0]);
}

After optimizing, the code becomes much clearer. The clever part of this approach is using the conditions as the object’s property names and the handling logic as the property values. When the button is clicked, the logic is determined by looking up the object’s properties. This method is particularly suited for unary conditions.

Multiple Conditional Logic

However, when the conditions become more complex, the above approach no longer works. For example:

const onButtonClick = (status, identity) => {
  if (identity == 'guest') {
    if (status == 1) {
      // ...
    } else if (status == 2) {
      // ...
    } else if (status == 3) {
      // ...
    } else if (status == 4) {
      // ...
    } else if (status == 5) {
      // ...
    } else {
      // ...
    }
  } else if (identity == 'master') {
    if (status == 1) {
      // ...
    } else if (status == 2) {
      // ...
    } else if (status == 3) {
      // ...
    } else if (status == 4) {
      // ...
    } else if (status == 5) {
      // ...
    } else {
      // ...
    }
  }
}

When faced with such complex conditions, the initial approach becomes impractical. Therefore, we need to optimize the original logic like this:

const actions = new Map([
  ['guest_1', () => {/* ... */}],
  ['guest_2', () => {/* ... */}],
  ['guest_3', () => {/* ... */}],
  ['guest_4', () => {/* ... */}],
  ['guest_5', () => {/* ... */}],
  ['master_1', () => {/* ... */}],
  ['master_2', () => {/* ... */}],
  ['master_3', () => {/* ... */}],
  ['master_4', () => {/* ... */}],
  ['master_5', () => {/* ... */}],
  ['default', () => {/* ... */}],
]);

const onButtonClick = (identity, status) => {
  let action = actions.get(`${identity}_${status}`) || actions.get('default');
  action.call(this);
}

The core logic in the above code is: concatenate two conditions into a single string, use the concatenated condition string as the key, and the corresponding handler function as the value. This allows you to look up and execute functions using a Map object, making it particularly useful for multi-condition logic.