前言:
我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得越来越臃肿,同时可读性也变差,越来越看不懂,那么如何更优雅的写判断逻辑,那么下面分析:
简单的if else
当你的业务是简单的双面判断时(非真即假):
你可能会这么写
// param {Boolean} falg :true or false
let txt = '';
if(falg){
txt = "成功"
}else{
txt = "失败"
}
这么写不是一种最优的写法,同时代码不够简洁,换种思路,直接上三目运算:
let txt = flag ? "成功" : "失败" ;
当出现多个 if else
你可能会这么写
// param {status} status 活动状态:1:成功 2:失败 3:进行中 4:未开始
let txt = '';
if(status == 1){
txt = "成功" ;
}else if(status == 2){
txt = "失败" ;
}else if(status == 3){
txt = "进行中" ;
}else{
txt = "未开始" ;
}
首先,你可能会想到switch case
let txt = '';
switch(status){
case 1:
txt = "成功" ;
break ;
case 2:
txt = "成功" ;
break ;
case 3:
txt = "进行中" ;
break ;
default:
txt = "未开始" ;
}
这种多条件判断,条件多了,代码也很臃肿,我们不妨使用对象的key value形式试试,上面代码继续优化:
const statusMap = {
1:"成功",
2:"失败",
3:"进行中",
4:"未开始"
}
调用直接 statusMapp[status] 解决!
wooo~ 你会发现,代码如此简洁!!!是不是看着也觉得很舒服~
使用es6 Map
如果你觉得以上代码还不是最理想的,可以试试Map
const actions = new Map([
[1, "成功"],
[2, "失败"],
[3, "进行中"],
[4, "未开始"]
])
调用直接 actions.get(status) 解决!
我们需要把问题升级一下,以前按钮点击时候只需要判断status,现在还需要判断用户的身份:
/**
* 按钮点击事件
* @param {number} status 活动状态:活动状态:1:成功 2:失败 3:进行中 4:未开始
* @param {string} identity 身份标识:admin 管理员 user 用户
*/
const handle = (status,identity)=>{
if(identity == 'admin'){
if(status == 1){
//do sth
}else if(status == 2){
//do sth
}else if(status == 3){
//do sth
}else if(status == 4){
//do sth
}else if(status == 5){
//do sth
}else {
//do sth
}
}else if(identity == 'user') {
if(status == 1){
//do sth
}else if(status == 2){
//do sth
}else if(status == 3){
//do sth
}else if(status == 4){
//do sth
}else if(status == 5){
//do sth
}else {
//do sth
}
}
}
原谅我不写每个判断里的具体逻辑了,因为代码太冗长了。
原谅我又用了if/else,因为我看到很多人依然在用if/else写这种大段的逻辑判断。
那么,怎么写才能优雅和简洁呢 ???
同理,使用Map
const actions = new Map([
['admin_1', ()=>{/*do sth*/}],
['admin_2', ()=>{/*do sth*/}],
['admin_3', ()=>{/*do sth*/}],
['admin_4', ()=>{/*do sth*/}],
['admin_5', ()=>{/*do sth*/}],
['user_1', ()=>{/*do sth*/}],
['user_2', ()=>{/*do sth*/}],
['user_3', ()=>{/*do sth*/}],
['user_4, ()=>{/*do sth*/}],
['user_5, ()=>{/*do sth*/}],
['default', ()=>{/*do sth*/}],
])
const handle = (identity,status)=>{
let action = actions.get(`${identity}_${status}`) || actions.get('default')
action.call(this)
}
当然上述代码如果用Object对象来实现也是类似的:
const actions = {
'admin_1':()=>{/*do sth*/},
'admin_2:()=>{/*do sth*/},
'admin_3:()=>{/*do sth*/},
//....
}
升级下问题,假如admin情况下,status1-4的处理逻辑都一样怎么办,最差的情况是这样:
const actions = new Map([
['admin_1', ()=>{/*function A*/}],
['admin_2', ()=>{/*function A*/}],
['admin_3', ()=>{/*function A*/}],
['admin_4', ()=>{/*function A*/}],
['admin_5', ()=>{/*function B*/}],
])
显然,function A重复写了4次,也不是很好的办法,然后我们尝试缓存functionA、 function B
const actions = ()=>{
const functionA = ()=>{/*do sth*/}
const functionB = ()=>{/*do sth*/}
return new Map([
['admin_1', functionA],
['admin_2', functionA],
['admin_3', functionA],
['admin_4', functionA],
['admin_5', functionB],
//...
])
}
如果status超过10条或者更多,代码同样很臃肿,那么我们可以在以上代码加上正则匹配:
const actions = ()=>{
const functionA = ()=>{/*do sth*/}
const functionB = ()=>{/*do sth*/}
return new Map([
[/^admin_[1-4]$/,functionA],
[/^admin_5$/,functionB],
//...
])
}
const handle = (identity,status)=>{
let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))
action.forEach(([key,value])=>value.call(this))
}
基于上面这种形式,我们就有很多的变化来适应我们的业务
例如场景是这样的, identity 身份标识:admin 管理员 user 用户
admin,1-4,执行functionA ,5执行functionB,5-9执行functionC,9以上的状态执行functionD,我们可以变化出以下代码:
const actions = ()=>{
const functionA = ()=>{/*do sth*/}
const functionB = ()=>{/*do sth*/}
const functionC = ()=>{/*do sth*/}
const functionD = ()=>{/*do sth*/}
return new Map([
[/^admin_[1-4]$/,functionA],
[/^admin_5$/,functionB],
[/^admin_[6-9]$/,functionC],
[/^admin_[1-9]\d$/,functionD],
//...
])
}
总结 :
本文已经教你了8种逻辑判断写法,包括:
1: if else
2: 三目运算
3: 一元判断时:使用object的key value
4: 一元判断时:使用Map
5: 多元判断时:将condition拼接成字符串存放到Object里
6: 多元判断时:将condition拼接成字符串存放到Map
7: 多元判断时:将condition拼接成字符串存放到Map,配合正则使用
最后:
- 大家感觉写得不错,可以点个赞和关注吧~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。