优化代码:少写点if else和switch

论坛 期权论坛 期权     
程序IT圈   2019-7-14 23:32   3954   0
点击上方“程序IT圈”,选择“置顶公众号”每天早晨8点50分,准点开车打卡
作者:潇湘待雨
cnblogs.com/pqjwyn/p/10247336.html
[h2]前言[/h2]作为搬砖在第一线的底层工人,业务场景从来是没有做不到只有想不到的复杂。
不过他强任他强,if-else全搞定,搬就完了。但是随着业务迭代或者项目交接,自己在看自己或者别人的if代码的时候,心情就不再表述了,各自深有体会。所以我们一起看看if还能怎么写
[h2]最基本if-else[/h2]假设有这么个场景,不同情况下打印不同值。
因为涉及到的条件太多,就不提三目运算之类优化了。
  1. if (a == 1) {
  2.     console.log('a1')
  3. } else if (a == 2) {
  4.     console.log('b2')
  5. } else if (a == 3) {
  6.     console.log('c3')
  7. } else if (a == 4) {
  8.     console.log('d4')
  9. }
  10. /* n..... */
复制代码
现在还算能看,因为逻辑简单,如果逻辑复杂,迭代多个版本之后,你还敢动吗。
每动一下就战战兢兢,谁知道哪里会遗漏。
那么换种方式呢
[h2]switch-case[/h2]这样稍微清晰那么一点,差别好像没什么差别:
  1. switch(a){
  2.     case 1:
  3.         console.log('a1');
  4.         break;
  5.     /* 省略。。。 */
  6.     case 40:
  7.         console.log('a40');
  8.         break;
  9. }
复制代码
[h2]分离配置信息与执行动作[/h2]object映射
定义一个object作为配置对象来存放不同状态,通过链表查找
  1. const statusMap = {
  2.     1:()=>{
  3.         console.log('a1')
  4.     },
  5.     2:()=>{
  6.         console.log('b2')
  7.     }
  8.     /* n.... */
  9. }
  10. // 执行
  11. let a = 1
  12. statusMap[a || 1]()
复制代码
这样比较清晰,将条件配置与具体执行分离。如果要增加其他状态,只修改配置对象即可。
数组映射
当然在某些状态下可以使用数组,来做这个配置对象。
  1. // 这里就涉及其他优化了,例如将执行函数抽离出来,大家不要关注func的内容就好。
  2. // 它就是个function,内容很复杂
  3. const statusArr = [function(){
  4.     console.log(1)
  5. },
  6.     function () {
  7.         console.log(2)
  8.     },]
  9. // 执行
  10. let a = 1
  11. statusArr[a || 1]()
复制代码
数组的要求更高一点,如果是其他key,例如字符串,那么数组就不能满足需求了
[h2]升级版:不同key相同value[/h2]这样看起来好一点了,那么需求又有变动了,
前面是每种处理方式都不同,下面有几种情况下处理函数相同的,例如1-39的时候,调用a,40之后调用b,如果我们继续来用映射的方式来处理。
  1. function f1 (){
  2.     console.log(1)
  3. }
  4. function f2 (){
  5.     console.log(2)
  6. }
  7. const statusMap={
  8.     1:f1,
  9.     2:f1,
  10.     3:f1,
  11.     4:f1,
  12.     //省略
  13.     40:f2
  14. }
  15. let a = 2
  16. statusMap[a]()
复制代码
这样当然也可以,不过重复写那么多f1,代码看起来不够简洁。
开始重构之前我们先捋一下思路,无非是想把多个key合并起来,对应一个value。也就是说我们的键值不是字符串而是个数组,object显然只支持字符串,那么可以将这么多key合并成一个:'1,2,3,4,..,9'。
但是查找的时候有点问题了,我们的参数肯定不能完全匹配。
接着走下去,是不是做个遍历加个判断,包含在子集内的都算匹配,那么代码看起来就是下面这个样子。
  1. // 将键值key设置为一个拼接之后的字符串
  2. const statusMap = {
  3.     '1,2,3,4,5': f1,
  4.     //省略
  5.     40: f2
  6. }
  7. // 获取所有的键值,待会遍历用
  8. const keys = Object.keys(statusMap),
  9.     len = keys.length
  10. // 遍历获取对应的值
  11. const getVal=(param='')=>{
  12.     // 用for循环的原因在于匹配之后就不需要继续遍历
  13.     for (let i = 0; i < len; i++) {
  14.         const key = keys[i],
  15.             val = statusMap[key]
  16.         // 这里用什么来判断就随便了,两个字符串都有。   
  17.         if (key.includes(param)) {
  18.             return val
  19.         }
  20.     }
  21. }
  22. let a = 2,
  23.     handle = getVal(a)
  24. handle() // 1
复制代码
但是这样来看,增加了个遍历的过程,而且是拼接字符串,万一哪天传了个逗号进来,会得到了预料之外的结果。
map
es6有个新的数据结构Map,支持任意数据结构作为键值。如果用Map可能更清晰一点。
  1. /**
  2. * map键值索引的是引用地址,
  3. * 如果是下面这样的写法不好意思,永远得不到值
  4. * map1.set([1,4,5],'引用地址')
  5. * map1.get([1,4,5])  //输出为undefined
  6. * 就像直接访问
  7. * map1.get([1,2,3,4,5]) //同样为undefined
  8. */
  9. const map1 = new Map()
  10. const statusArr = [1,2,3,4,5]
  11. map1.set(statusArr,f1)
  12. // 预设默认值,因为不能直接遍历
  13. let handle = function(){}
  14. const getVal = (param = '') => {
  15. for (let value of map1.entries()) {
  16.     console.log(JSON.stringify(value))
  17.     if (value[0].includes(param)){
  18.         console.log(value)
  19.         // 不能跳出 只能处理了
  20.         handle = value[1]
  21.     }
  22. }
  23. }
  24. const a = 2
  25. getVal(a)
  26. handle()
复制代码
个人而言虽然这样减少了重复代码,但是又增加了一步匹配值的操作,优劣就见仁见智吧。
双数组
肯定有部分人就是不想做遍历的操作,既然一个数组不能满足,那么两个数组呢。
  1. // 键值数组和value 保持对应关系
  2. const keyArr = ['1,2,3,4,5','40']
  3. const valArr = [f1,f2]
  4. const getVal = (param = '')=>{
  5.     // 查找参数对应的下标
  6.     let index = keyArr.findIndex((it)=>{
  7.         return it.includes(param)
  8.     })
  9.     // 获取对应值
  10.     return valArr[index]
  11. }
  12. let a = 2,
  13.     handle = getVal(a)
  14. handle()
复制代码
利用数组提供的下标,将key和value对应起来,进而获取想要的值。
这里一直没有达到我最初的目的,即键里面重复的数组,可以不通过多余操作匹配到,上面不管怎么样都进行了处理,这不是懒人的想要的。
[h2]总结[/h2]这是在写业务需求的时候做的一点总结,数组和对象的映射可能大家都在用。当遇到了不同key相同value的情况时,从懒出发不像重复罗列,就尝试了下。当然了,因为个人水平问题,肯定有更好的处理方式,欢迎一起讨论,抛砖引玉共同进步。此外现有成熟的库里loadsh也是可以到达目的,不过自己思考过之后再去看大神的作品理解会更深入一点。


回馈公众号真爱粉的一次活动!
给你一份Spring Boot核心知识清单
【漫画】大家都已被垃圾分类逼疯了!
推荐个交流氛围非常不错的微信群


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:25
帖子:5
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP