您现在的位置是:群英 > 开发技术 > 编程语言
if/else 和 switch怎样才能写出更优雅的判断逻辑
Admin发表于 2022-04-26 14:23:24870 次浏览
这篇文章给大家分享的是“if/else 和 switch怎样才能写出更优雅的判断逻辑”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“if/else 和 switch怎样才能写出更优雅的判断逻辑”吧。

我们在编写 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´)
      break
    case 2:
    case 3:
      sendLog(´fail´)
      jumpTo(´FailPage´)
      break
    case 4:
      sendLog(´success´)
      jumpTo(´SuccessPage´)
      break
    case 5:
      sendLog(´cancel´)
      jumpTo(´CancelPage´)
      break
    default:
      sendLog(´other´)
      jumpTo(´Index´)
      break
  }
}


好吧,看起来比 if/else 层次结构更清晰一些,细心的读者可能也发现了一个小窍门:case 2 和 case 3 的逻辑一样时,可以把前面的逻辑处理代码省略,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])
}


使用 Map 代替 Object 有很多优点,Map 对象和普通对象有的区别是:


1.一个对象通常有自己的原型,所以一个对象总是有一个“prototype”键

2.对象的键只能是一个字符串或符号,但 Map 的键可以是任何值

3.你可以通过使用 size 属性很容易得到 Map 中的键值对的数量,而一个对象中的键值对数量不能直接获取


现在我们来升级一下这个问题的难度。点击按钮时,不仅要判断状态,还要判断用户的身份。

const onButtonClick = (status, identity) => {
  if (identity == ´guest´) {
    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 == ´master´) {
    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
    }
  }
}


从上面的例子中可以看到,当你的逻辑升级到双重判断的时候,你的判断力就会加倍,你的代码就会加倍。

如何才能让代码更干净利落呢?


这里有一个解决方案。

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 的键,然后在查询时直接查询对应字符串的值。当然,我们也可以在这里把 Map 改成 Object。

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


如果读者觉得把查询拼成一个字符串有点尴尬,还有另一个解决办法,那就是用一个 Map 对象作为 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 和普通对象的区别,其中 Map 可以用任何类型的数据作为键。现在让我们把它的难度再提高一点。如果对于 guest 身份来说,状态 1-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))
}


这对于日常需求来说已经足够了,但是说真的,函数 A 被引用了 4 次,还是有点烦人。

如果事情真的变得很复杂,比如身份有 3 种,状态有 10 种,你需要定义 30 个处理逻辑,其中很多处理逻辑都是一样的,这似乎让人无法接受。


而你可以这样做:

const actions = () => {
  const functionA = () => {} // 逻辑处理 A
  const functionB = () => {} // 逻辑处理 B
  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 而不是 Object 的优势比较明显,因为可以用正则式作为键。

如果需求变成:所有的对 guest 操作都需要发送一个日志埋点,不同状态的 guest 可能有不同的逻辑处理,那么我们可以写成如下:

const actions = () => {
  const functionA = () => {} // 逻辑处理 A
  const functionB = () => {} // 逻辑处理 B
  const functionC = () => {} // 发送日志 C
  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))
}


这样一来,公共逻辑和单个逻辑可以同时执行。


总结

本文讲到了八种 JS 逻辑判断的写法,包括:

1.if/else

2.switch

3.单一判断:存储在 Object 中

4.单一判断:存储在 Map 对象中

5.多重判断:将条件串联成一个字符串,存储在 Object 中

6.多重判断:将条件连成一个字符串,存储在 Map 对象中

7.多重判断:把条件作为对象存储在 Map 中

8.多重判断:把条件写成正则式存储在 Map 中


以上就是关于“if/else 和 switch怎样才能写出更优雅的判断逻辑”的介绍了,感谢各位的阅读,希望文本对大家有所帮助。如果想要了解更多知识,欢迎关注群英网络,小编每天都会为大家更新不同的知识。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: JS逻辑判断
相关信息推荐
2022-02-25 17:19:07 
摘要:这篇文章给大家分享一个Python示例,打印生日快乐这四个字,小编觉得挺有趣的,因此分享给大家做个参考,实现代码及效果如下,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
2022-05-07 17:06:34 
摘要:实现方法:1、利用“<div class="pre-scrollable">”排版类实现滚动条;2、利用“<div style="overflow:scroll;width:宽度;height:高度;">”实现滚动条。
2022-05-06 17:56:18 
摘要:这篇文章主要为大家详细介绍了用C语言实现通讯录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部