JavaScript 逻辑判断进阶:从 if-else 到 Map 的高级用法

作者:异步漫步时间:2026-10-23 19:04:15浏览:130

本文深入探讨 JavaScript 中复杂逻辑判断的多种实现方式。从基础的 if-else 和 switch 语句出发,逐步演示如何利用对象属性映射和 Map 对象简化单一条件判断。针对多重条件场景,介绍了字符串拼接键、嵌套 Map 以及正则表达式匹配等高级技巧,旨在帮助开发者写出更简洁、易维护且高效的代码。

JavaScript 逻辑判断的演进

在 JavaScript 开发中,处理复杂的业务逻辑判断是常见需求。虽然 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 语句进行重构。

使用 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
 }
}

重构后的 switch 结构确实比嵌套的 if-else 更加清晰。值得注意的是,当 case 2 和 case 3 执行相同的逻辑时,可以省略 case 2 中的处理代码,利用 case 穿透特性,使 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)
}

这种写法显著提升了代码的整洁度。其核心思想是将判断条件作为对象的键,将处理逻辑作为对应的值。在按钮点击时,通过对象属性查找的方式直接获取并执行逻辑,这种方法特别适用于单一条件的判断场景。

既然对象映射有效,是否还有其他编码方式?答案是肯定的。

Map 对象在单一判断中的应用


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 对象替代普通对象具有诸多优势,主要区别体现在以下几个方面:

  • 普通对象通常继承自原型链,因此始终包含一个 'prototype' 键。
  • 普通对象的键只能是字符串或符号类型,而 Map 的键可以是任意类型的值。
  • Map 提供了 size 属性,可以方便地获取键值对的数量;而普通对象的键值对数量无法直接通过属性获取。

接下来提升问题难度:点击按钮时,除了判断状态,还需要判断用户身份。

双重判断带来的代码膨胀问题


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 也可以替换为普通对象。


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

如果读者认为拼接字符串的方式不够直观,还有另一种解决方案:使用 Map 对象作为键。

使用 Map 对象作为键的多重判断


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 逻辑判断方式

总结

本文介绍了八种 JavaScript 逻辑判断的写法,包括:

  1. if-else 语句
  2. switch 语句
  3. 单一判断:存储在 Object 中
  4. 单一判断:存储在 Map 对象中
  5. 多重判断:将条件串联成一个字符串,存储在 Object 中
  6. 多重判断:将条件连成一个字符串,存储在 Map 对象中
  7. 多重判断:把条件作为对象存储在 Map 中
  8. 多重判断:把条件写成正则式存储在 Map 中

至此,关于 JS 逻辑判断不再局限于 if-else 和 switch 的探讨结束。更多相关 js 逻辑判断 if else switch 内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章