消除 if-else 条件判断
用策略模式、对象映射等方式优化冗长的条件判断
问题
代码中大量的 if-else 嵌套会导致可读性差、难以维护。如何优雅地消除这些条件判断?
解答
1. 对象映射(策略模式)
最常用的方式,用对象的 key-value 替代条件分支。
// ❌ 糟糕的写法
function getPrice(type) {
if (type === 'regular') {
return 10
} else if (type === 'premium') {
return 20
} else if (type === 'vip') {
return 30
} else {
return 0
}
}
// ✅ 对象映射
function getPrice(type) {
const priceMap = {
regular: 10,
premium: 20,
vip: 30
}
return priceMap[type] ?? 0
}
2. Map 处理复杂键
当键不是简单字符串时,使用 Map。
// 复合条件作为键
const actionMap = new Map([
['guest_view', () => console.log('游客浏览')],
['user_edit', () => console.log('用户编辑')],
['admin_delete', () => console.log('管理员删除')]
])
function handleAction(role, action) {
const key = `${role}_${action}`
const handler = actionMap.get(key)
handler?.()
}
handleAction('admin', 'delete') // 管理员删除
3. 数组 find 处理范围判断
// ❌ 多个 if-else 判断范围
function getGrade(score) {
if (score >= 90) return 'A'
else if (score >= 80) return 'B'
else if (score >= 60) return 'C'
else return 'D'
}
// ✅ 数组配置 + find
function getGrade(score) {
const gradeRules = [
{ min: 90, grade: 'A' },
{ min: 80, grade: 'B' },
{ min: 60, grade: 'C' },
{ min: 0, grade: 'D' }
]
return gradeRules.find(rule => score >= rule.min).grade
}
4. 提前返回(卫语句)
减少嵌套层级,让主逻辑更清晰。
// ❌ 嵌套地狱
function processUser(user) {
if (user) {
if (user.isActive) {
if (user.hasPermission) {
// 真正的业务逻辑
return doSomething(user)
} else {
return 'no permission'
}
} else {
return 'inactive'
}
} else {
return 'no user'
}
}
// ✅ 提前返回
function processUser(user) {
if (!user) return 'no user'
if (!user.isActive) return 'inactive'
if (!user.hasPermission) return 'no permission'
// 主逻辑
return doSomething(user)
}
5. 可选链 + 空值合并
处理空值判断的简洁写法。
// ❌ 繁琐的空值判断
function getUserCity(user) {
if (user && user.address && user.address.city) {
return user.address.city
}
return '未知'
}
// ✅ 可选链 + 空值合并
function getUserCity(user) {
return user?.address?.city ?? '未知'
}
6. 多态(面向对象场景)
// 不同类型有不同行为时,用类的多态
class Shape {
getArea() {
throw new Error('子类必须实现')
}
}
class Circle extends Shape {
constructor(radius) {
super()
this.radius = radius
}
getArea() {
return Math.PI * this.radius ** 2
}
}
class Rectangle extends Shape {
constructor(width, height) {
super()
this.width = width
this.height = height
}
getArea() {
return this.width * this.height
}
}
// 使用时无需判断类型
const shapes = [new Circle(5), new Rectangle(4, 6)]
shapes.forEach(s => console.log(s.getArea()))
关键点
- 对象映射是最常用的方式,适合简单的一对一映射
- Map 适合复杂键或需要保持插入顺序的场景
- 提前返回能有效减少嵌套,让代码更扁平
- 可选链
?.和空值合并??是处理空值的利器 - 不要过度优化,简单的 2-3 个分支用 if-else 反而更直观
目录