if...else是我们平时写代码时经常用到的,而且使用起来也没啥问题。问题是当业务逻辑比较复杂时,一堆条件判断就看的让人头大了,而且功能迭代时,还有可能在上面进行增量修改,内容越来越长,嵌套越来越深,可读性就变得越来越差。作为一个有追求的银,不但要求功能能实现,还要尽可能的美观好看~
接下来,我们就从几个方面来给代码换装
三元表达式
if (status === 'A') {
handleA();
} else {
handleOther();
}
像这种简单的if...else可以直接用三元表达式替换
status === 'A' ? handleA() : handleOther();
跟上面代码相比,少了好几行呢是吧,哈哈。
函数封装
function fn () {
if (A) {
// TODO
}
if (B) {
// TODO
}
if (C) {
// TODO
}
}
上面的这种代码是很常见的,根据不同的状态执行不同的逻辑,但是所有的逻辑处理堆到一个函数里面就会使这个函数体变得很大。本着单一性的原则,我们可以把代码进行拆分,每个if里面的逻辑处理封装成一个函数,这样看起来会比较清晰。
function handleA () {
// TODO
}
function handleB () {
// TODO
}
function handleC () {
// TODO
}
function fn () {
if (A) {
handleA();
}
if (B) {
handleB();
}
if (C) {
handleC();
}
}
对象封装
if (status === 'A') {
// TODO
} else if (status === 'B') {
// TODO
} else if (status === 'C') {
// TODO
}
像这种if..else if...的格式,从上到下判断,只会进入其中一个分支, 而且条件都是用一个全等就能判断出来的,可以利用对象键值对的形式,状态条件作为键,值是一个函数去执行业务逻辑来进行封装。
const map = {
A: () => {},
B: () => {},
C: () => {}
}
map[status]();
每个分支的逻辑都被写成一个独立的函数,之后再有不同的条件判断,丰富对象键值对就行了,清晰明了。
或者用es6的Map
const map = new Map([
['A', () => {}],
['B', () => {}],
['C', () => {}]
])
const action = map.get(status);
action();
Map与Object的区别是Map可以用任何类型的数据作为key。
也可以用switch语句:
switch (status) {
case 'A':
// TODO
break;
case 'B':
// TODO
break;
default:
// TODO
}
不用写那么多'==='了,不过switch判断的是'==='而不是'=='.
这是条件状态很单一的时候,那条件判断比较复杂的时候呢?比如 a && b && c 之类的,可以把条件也作为一个函数存储起来,当函数返回true时,执行对应的逻辑处理函数。
const rules = [
{
match: (a, b, c) => {}, // 条件判断
action: () => {} // 对应的业务逻辑
},
{
match: (a, b, c) => {},
action: () => {}
},
{
match: (a, b, c) => {},
action: () => {}
}
]
for (let i = 0; i < rules.length; i++) {
if (rules[i].match(a, b, c)) { // 只要条件判断返回true,就执行对应的业务逻辑,并结束循环
return rules[i].action(a, b, c)
}
}
以上只是条件语句比较复杂数量比较多时的代码优化方法,if...else该用还得用,用的时候尽量把常用的条件体放到前面,这样找到正确分支的速度就会快。