今天在掘金上看到一篇文章,讲的是遇到很多if-else的情况下,如何换一种思路,让代码的可读性更好。在这里整理一下从那篇文章学到的东西。
当遇到如下需求的时候:给某个班级的学生成绩进行评级,满分100分。90分以上→成绩极好;80分-90分→成绩优秀;70分-80分→成绩良好;60分-70分→成绩一般;0分-60分→成绩不及格;
按照我习惯的写法,肯定就是不假思索的用几个if-else套进去开始写(先把功能实现了再说 -_-):
// 传统的if-else写法
function scoreRating (grade) {
let level = ''
if (grade >= 90) {
level = '成绩极好'
} else if (grade >= 80) {
level = '成绩优秀'
} else if (grade >= 70) {
level = '成绩良好'
} else if (grade >= 60) {
level = '成绩一般'
} else {
level = '成绩不及格'
}
return level
}
scoreRating(32) // 成绩不及格
这样也能运行出结果,但是缺点:
- 如果改需求,改变评级的文案或者是分数等级,整个的代码都需要改
- 这么多if-else确实有点不好看,应该有更好的写法
尝试改成下面的,配置数据和业务逻辑分开:
function scoreRating (grade) {
let gradeLevel = [90, 80, 70, 60]
let gradeTxt = ['成绩极好', '成绩优秀', '成绩良好', '成绩一般', '成绩不及格']
for (let i=0, len=gradeLevel.length; i= gradeLevel[i]) {
return gradeTxt[i]
}
}
// 否则,返回‘成绩不合格’
return gradeTxt[gradeTxt.length-1]
}
这样写的好处:
- 如果更改需求,只需要改gradeLevel,gradeTxt就可以了
- 避免修改业务逻辑,降低风险
上面的方法在课本中被称为表驱动法
。
在简单的情况下,逻辑语句往往更简单也更直接。但是随着逻辑链的复杂,表就变得越来越富有吸引力了。
举个例子,假设需要一个返回每个月多少天的函数,用if-else的方法:
function getMonthDays (month) {
let day = ''
if (month === 1) {day = 31}
else if (month === 2) {day = 28}
else if (month === 3) {day = 31}
else if (month === 4) {day = 30}
// 中间的几个月份省略
...
...
...
else if (month === 12) {day = 31}
return day
}
上面的代码显得很冗余,换成表驱动法,就可以这样:
function getMonthDays(month) {
// 这两行代码只是简单的表达意思...
let day = [31,28,31,30,31,30,31,31,30,31,30,31]
return day[month-1]
}
这样看起来清爽很多。
在这里通过上面的简单例子,引出表驱动法。
表驱动法的意义在于:逻辑和数据分离。因为在程序中,修改数据和修改逻辑的方法是不同的,成本也不同。数据的添加是相对简单低风险的,但是增加或修改逻辑的风险和成本是很高的。
最后:
在工作中在合适的场景,可以考虑用表驱动法改写冗余的if-else