前提

我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得越来越臃肿,越来越看不懂,那么如何更优雅的写判断逻辑,本文带你试一下。

举个例子

先看一段代码

const onButtonClick = (status)=>{if(status == 1){sendLog('processing')jumpTo('IndexPage')}else if(status == 2){sendLog('fail')jumpTo('FailPage')}else if(status == 3){sendLog('fail')jumpTo('FailPage')}else if(status == 4){sendLog('success')jumpTo('SuccessPage')}else if(status == 5){sendLog('cancel')jumpTo('CancelPage')}else {sendLog('other')jumpTo('Index')}
}

通过代码可以看到这个按钮的点击逻辑:根据不同活动状态做两件事情,发送日志埋点和跳转到对应页面,大家可以很轻易的提出这段代码的改写方案,switch出场:

const onButtonClick = (status)=>{switch (status){case 1:sendLog('processing')jumpTo('IndexPage')breakcase 2:case 3:sendLog('fail')jumpTo('FailPage')break  case 4:sendLog('success')jumpTo('SuccessPage')breakcase 5:sendLog('cancel')jumpTo('CancelPage')breakdefault:sendLog('other')jumpTo('Index')break}
}

嗯,这样看起来比if/else清晰多了,细心的同学也发现了小技巧,case 2和case 3逻辑一样的时候,可以省去执行语句和break,则case 2的情况自动执行case 3的逻辑。

这时有同学会说,还有更简单的写法:

const actions = {'1': ['processing','IndexPage'],'2': ['fail','FailPage'],'3': ['fail','FailPage'],'4': ['success','SuccessPage'],'5': ['cancel','CancelPage'],'default': ['other','Index'],
}const onButtonClick = (status)=>{let action = actions[status] || actions['default'],logName = action[0],pageName = action[1]sendLog(logName)jumpTo(pageName)
}

上面代码确实看起来更清爽了,这种方法的聪明之处在于:将判断条件作为对象的属性名,将处理逻辑作为对象的属性值,在按钮点击的时候,通过对象属性查找的方式来进行逻辑判断,这种写法特别适合一元条件判断的情况。

是不是还有其他写法呢?有的:

const actions = new Map([[1, ['processing','IndexPage']],[2, ['fail','FailPage']],[3, ['fail','FailPage']],[4, ['success','SuccessPage']],[5, ['cancel','CancelPage']],['default', ['other','Index']]
])const onButtonClick = (status)=>{let action = actions.get(status) || actions.get('default')sendLog(action[0])jumpTo(action[1])
}

这样写用到了es6里的Map对象,是不是更爽了?Map对象和Object对象有什么区别呢?

  1. 一个对象通常都有自己的原型,所以一个对象总有一个”prototype”键。
  2. 一个对象的键只能是字符串或者Symbols,但一个Map的键可以是任意值。
  3. 你可以通过size属性很容易地得到一个Map的键值对个数,而对象的键值对个数只能手动确认。

我们需要把问题升级一下,以前按钮点击时候只需要判断status,现在还需要判断用户的身份:

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 {}}
}

原谅我不写每个判断里的具体逻辑了,因为代码太冗长了。

原谅我又用了if/else,因为我看到很多人依然在用if/else写这种大段的逻辑判断。

从上面的例子我们可以看到,当你的逻辑升级为二元判断时,你的判断量会加倍,你的代码量也会加倍,这时怎么写更清爽呢?

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)
}

上述代码核心逻辑是:把两个条件拼接成字符串,并通过以条件拼接字符串作为键,以处理函数作为值的Map对象进行查找并执行,这种写法在多元条件判断时候尤其好用。

当然上述代码如果用Object对象来实现也是类似的:

const actions = {'guest_1':()=>{},'guest_2':()=>{},}const onButtonClick = (identity,status)=>{let action = actions[`${identity}_${status}`] || actions['default']action.call(this)
}

如果有些同学觉得把查询条件拼成字符串有点别扭,那还有一种方案,就是用Map对象,以Object对象作为key:

const actions = new Map([[{identity:'guest',status:1},()=>{}],[{identity:'guest',status:2},()=>{}],])const onButtonClick = (identity,status)=>{let action = [...actions].filter(([key,value])=>(key.identity == identity && key.status == status))action.forEach(([key,value])=>value.call(this))
}

是不是又高级了一点点?

这里也看出来Map与Object的区别,Map可以用任何类型的数据作为key。

我们现在再将难度升级一点点,假如guest情况下,status1-4的处理逻辑都一样怎么办,最差的情况是这样:

const actions = new Map([[{identity:'guest',status:1},()=>{}],[{identity:'guest',status:2},()=>{}],[{identity:'guest',status:3},()=>{}],[{identity:'guest',status:4},()=>{}],[{identity:'guest',status:5},()=>{}],])

好一点的写法是将处理逻辑函数进行缓存:

const actions = ()=>{const functionA = ()=>{}const functionB = ()=>{}return new Map([[{identity:'guest',status:1},functionA],[{identity:'guest',status:2},functionA],[{identity:'guest',status:3},functionA],[{identity:'guest',status:4},functionA],[{identity:'guest',status:5},functionB],])
}const onButtonClick = (identity,status)=>{let action = [...actions()].filter(([key,value])=>(key.identity == identity && key.status == status))action.forEach(([key,value])=>value.call(this))
}

这样写已经能满足日常需求了,但认真一点讲,上面重写了4次functionA还是有点不爽,假如判断条件变得特别复杂,比如identity有3种状态,status有10种状态,那你需要定义30条处理逻辑,而往往这些逻辑里面很多都是相同的,这似乎也是笔者不想接受的,那可以这样实现:

const actions = ()=>{const functionA = ()=>{}const functionB = ()=>{}return new Map([[/^guest_[1-4]$/,functionA],[/^guest_5$/,functionB],])
}const onButtonClick = (identity,status)=>{let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))action.forEach(([key,value])=>value.call(this))
}

这里Map的优势更加凸显,可以用正则类型作为key了,这样就有了无限可能,假如需求变成,凡是guest情况都要发送一个日志埋点,不同status情况也需要单独的逻辑处理,那我们可以这样写:

const actions = ()=>{const functionA = ()=>{}const functionB = ()=>{}const functionC = ()=>{}return new Map([[/^guest_[1-4]$/,functionA],[/^guest_5$/,functionB],[/^guest_.*$/,functionC],])
}const onButtonClick = (identity,status)=>{let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))action.forEach(([key,value])=>value.call(this))
}

也就是说利用数组循环的特性,符合正则条件的逻辑都会被执行,那就可以同时执行公共逻辑和单独逻辑,因为正则的存在,你可以打开想象力解锁更多的玩法,本文就不赘述了。

总结

本文已经教你了8种逻辑判断写法,包括:

  1. if/else
  2. switch
  3. 一元判断时:存到Object里
  4. 一元判断时:存到Map里
  5. 多元判断时:将condition拼接成字符串存到Object里
  6. 多元判断时:将condition拼接成字符串存到Map里
  7. 多元判断时:将condition存为Object存到Map里
  8. 多元判断时:将condition写作正则存到Map里

至此,本文也将告一段落,愿你未来的人生里,不只是有if/else/switch。

JavaScript复杂判断的更优雅写法相关推荐

  1. JavaScript 复杂判断的更优雅写法

    我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得越来越臃 ...

  2. 【转】转自微信公众号 JavaScript 复杂判断的更优雅写法

    与微信公众号看到一篇js复杂判断的文章,对我启发很大,故转到博客园以供后期不断学习并应用于项目.原文地址:https://mp.weixin.qq.com/s/ClFDRj4MnAxv1dJ5VWKS ...

  3. JavaScript 复杂判断的更优雅写法借鉴

    前言: 我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得 ...

  4. python代码书写_Python代码的优雅写法,让代码更简洁

    我们都知道,Python 的设计哲学是「优雅」.「明确」.「简单」.这也许很多人选择 Python 的原因.但是我收到有些伙伴反馈,他写的 Python 并不优雅,甚至很臃肿,那可能是你的姿势不对哦! ...

  5. 更优雅的编写JavaScript,使用这些函数秒变大神

    如果你刚接触JavaScript可能你还没有听说过.map(),.reduce(),.filter().或者听说过,看过别人用过但是自己在实际项目中没有用过.在国内很多开发项目都是需要考虑IE8的兼容 ...

  6. javascript写字技巧_JavaScript 如何书写更优雅

    平时在写代码逻辑时,有些代码会很长,如何更简洁的书写,让我们的代码更优雅: 1.三目运算 当想写 if...else 语句时,使用三目运算来代替. var age = 20; var tip; if( ...

  7. html5判断text文本是数字,JavaScript常用判断写法大全

    js验证表单大全,用JS控制表单提交,具体内容如下所示: 1. 长度限制 function test() { if(document.a.b.value.length>50) { alert(& ...

  8. 6种更优雅书写Python代码!

    1 简介 一些比较熟悉pandas的读者朋友应该经常会使用query().eval().pipe().assign()等pandas的常用方法,书写可读性很高的「链式」数据分析处理代码,从而更加丝滑流 ...

  9. 读的, 且经过美化, 能在所有 JavaScript 环境中运行, 并且应该和对应手写的 JavaScript 一样快或者更快.

    目录 试一试 CoffeeScript 代码和注释 CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的 ...

最新文章

  1. Docker搭建Nacos1.3+Seata1.4+MySQL8分布式事务(服务端)
  2. python不是内部或外部命令的解决方法_详解python常见报错--NO MODULE NAMED _SQLITE3解决方法...
  3. php mysql 编码为utf-8_php连mysql用 utf-8编码乱码怎么办
  4. 如果王思聪是产品经理
  5. linux moxa 多串口卡_MOXA多串口卡C32030TCPU模块双RISC-based处理器架构大幅提升I/O数据传输的效能达到8口或以上...
  6. STM32:定时器中断与优先级
  7. PostgreSQL在何处处理 sql查询之五十三
  8. 创建表时参数PCTFREE和PCTUSED是什么意思?
  9. 360主机卫士Linux版,360主机卫士
  10. Mac下实现Word文档批量转换为PDF
  11. 中国大陆五级行政区划数据爬虫
  12. 6.CCS新建工程及配置
  13. 中国电信5G定制网产品要点
  14. B2B网关支付方案介绍
  15. iPad 手指触摸与PC鼠标事件
  16. 华为摄像头 SDC REST 接口对接 经验
  17. Java对象大小内幕浅析
  18. PAT甲级 1042 Shuffling Machine 模拟洗牌 map的使用
  19. Haroopad Markdown 编辑器代码语法高亮支持
  20. compareto返回1和-1的区别_温故篇:Comparable与Compatator的区别

热门文章

  1. java中将date插入mysql中date_JAVA 处理时间 - java.sql.Date、java.util.Date与数据库中的Date字段的转换方法[转]...
  2. CT基本概念(必须掌握)
  3. Anaconda2安装时出现问题
  4. windows7+visual studio 2013+CUDA7.5 编译caffe+配置matcaffe+配置pycaffe
  5. OpenCV伪彩色applyColorMap函数
  6. Ibatis.net 属性字段中使用 IN 查询条件
  7. 从运维的角度理解Iaas、Paas、Saas云计算
  8. 操作 Wave 文件(14): waveOutSetPlaybackRate、waveOutSetPitch
  9. SecureCRT提示----数据库里没找到防火墙“无”----解决方案
  10. centos 6.3 x86_64安装32位JDK的问题