消除 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 反而更直观