前端中如何优化if/else

3,713 阅读3分钟

前端中的if/else

在编写业务代码的时候,经常会出现条件判断,如果判断条件众多,就会出现if/else天梯,如果新的业务场景出现,就需要再添加一个if/else,这样的代码维护起来,简直是灾难。

if (status === 0) {
  //do something
} else if (status === 1) {
  //do something
} else if (status === 2) {
  //do something
} else if (status === 3) {
  // do something
}

如果新的业务场景出现,status === 4,那就需要再写一个if else,这样的代码可读性太差了。

简单if/else ----> 三元表达式

我们先从最简单的方式if/else进行改写 场景:

if (status === 0) {
  action()
} else {
  do();
}

像上面的状态判断,其实是没有必要的,那么如何进行判断的改写呢?

消除else

上面的else没有什么必要

if (status === 0) {
  action();
  return;
}
do();

使用三元表达式

status === 0 ? action() : do()

这样是不是更加简洁?毫无疑问

if/else 天梯转变为switch 天梯

经过了简单的if/else,那么我们来看一下,多重if/else如果进行改写?可以通过switch进行改良代码

switch (status) {
  case 0: 
    // ...
  case 1:
    // ...
  case 2:
    // ...
  default:
    //...
}

但是这样无非只是将if else转变为了switch,提高了代码的可读性。当遇到新的场景的时候,还是需要到switch里面去修改对应的代码。

使用map,将代码配置化

定义一个map,里面存储对应的状态和对应状态的操作

const statusMap = new Map([
  [0, doStatusZero],
  [1, doStatusOne],
  [2, doStatusThree]
]);
// 当遇到对应的状态的时候,只需要
statusMap.get(status)();

如果可以的化,可以将配置文件抽离,形成一个配置文件,如果有新的状态改变,只需要改变配置文件就ok了。

匹配对应的规则

使用map的好处,是代码可行性和整洁性提高了一个层次,但是只适用于一个单一的判断规则。如果具备多个判断的时候怎么办?假如一个判断是这样的,if(status === 0 && done === true && success == true), 那这样map简单配置的方式就不可以了,那既然简单不行,那就来电稍微复杂点的呗。

本质上if/else逻辑是一种状态匹配,转变为计算机的方式就是模式匹配,单一的模式不能满足需要,那就创建一个多元模式匹配。

场景:需要判断三种状态 status/done/success

多元状态匹配,需要进行两步操作

  • 判断状态是否匹配
  • 匹配完成要完成的动作

基于上面两种行为,我们将map抽象为下面的方式

const judgeMap = new Map([
  [
    (status, done, success) => status === 0 && done === 1 && success === 1,
    () => {
      // do something
    }
  ],
  [
    (status, done, success) => status === 1 && done === 1 && success === 1,
    () => {
      // do something
    }
  ]
]);

for (let [rule, action] of judgeMap) {
  rule(status, done, success) && action()
}

总结

其实整个思想来源于表驱动法,使用表数据,存储对应的状态处理。其中表的概念,不局限于一个简单的map也可能是一个数组或者对象甚至是一个字符串,表的结构可以自己定义。

常见例子

如何优雅地输出今天星期几?

`今天星期${'日一二三四五六'.charAt((new Date()).getDay())}`

上面的例子可以看到表就是一个字符串

参考资料

表驱动法
数据驱动编程