顾乔芝士网

持续更新的前后端开发技术栈

switch 语句的"替代品",对象映射让条件判断更简洁!

为了根据不同的条件执行不同的逻辑,传统的做法是使用 switch 语句或者多个 if-else 分支,但这些方法往往会让代码变得冗长且难以维护。

传统 switch 语句的痛点

让我们先看一个典型的 switch 语句示例:

function getStatusMessage(status) {
  switch (status) {
    case 'loading':
      return '正在加载...';
    case 'success':
      return '操作成功!';
    case 'error':
      return '操作失败,请重试';
    case 'timeout':
      return '请求超时';
    default:
      return '未知状态';
  }
}

这种写法存在几个问题:

  1. 代码冗长:每个 case 都需要写 break 语句
  2. 易出错:忘记写 break 会导致贯穿执行
  3. 可读性差:大量的样板代码影响核心逻辑的阅读
  4. 难以扩展:添加新条件需要修改函数内部

对象映射:更简洁的替代方案

基础用法

使用对象映射,上面的代码可以简化为:

const statusMessages = {
    loading: '正在加载...',
    success: '操作成功!',
    error: '操作失败,请重试',
    timeout: '请求超时'
};

function getStatusMessage(status) {
    return statusMessages[status] || '未知状态';
}

优势显而易见:

  • 代码量减少了 60%
  • 逻辑更清晰,一目了然
  • 不会出现忘记 break 的问题

函数映射:处理复杂逻辑

当需要执行复杂逻辑时,可以将值设为函数:

const userActions = {
    login: (user) => {
        console.log(`用户 ${user.name} 登录成功`);
        return { success: true, token: generateToken(user) };
    },
    logout: (user) => {
        console.log(`用户 ${user.name} 已退出`);
        clearUserSession(user.id);
        return { success: true };
    },
    register: (userData) => {
        const newUser = createUser(userData);
        console.log(`新用户 ${newUser.name} 注册成功`);
        return { success: true, user: newUser };
    }
};

function handleUserAction(action, data) {
    const handler = userActions[action];
    if (handler) {
        return handler(data);
    }
    throw new Error(`不支持的操作: ${action}`);
}

// 辅助函数(假设已实现)
function generateToken(user) {
    return 'mock-token-' + user.name;
}

function clearUserSession(userId) {
    console.log(`清除用户 ${userId} 的会话`);
}

function createUser(userData) {
    return { id: 'user-' + Date.now(), name: userData.name };
}

// 使用示例
const result = handleUserAction('login', { name: 'Alice', password: '123456' });
console.log(result); // 输出: { success: true, token: 'mock-token-Alice' }

Map 对象:更强大的键值映射

对于需要非字符串键的场景,可以使用 Map 对象:

const responseHandlers = new Map([
    [200, () => console.log('请求成功')],
    [404, () => console.log('资源未找到')],
    [500, () => console.log('服务器错误')],
    ['default', () => console.log('未知错误')]
]);

function handleResponse(statusCode) {
    const handler = responseHandlers.get(statusCode) || responseHandlers.get('default');
    handler();
}

// 使用示例
handleResponse(200);   // 输出: "请求成功"
handleResponse(404);   // 输出: "资源未找到"
handleResponse(999);   // 输出: "未知错误"

高级应用场景

多条件映射

const discountRules = {
    'vip-new': 0.8,    // VIP新用户8折
    'vip-old': 0.9,    // VIP老用户9折
    'normal-new': 0.95,    // 普通新用户95折
    'normal-old': 1.0    // 普通老用户原价
};

function calculatePrice(userType, isNewUser, originalPrice) {
    const key = `${userType}-${isNewUser ? 'new' : 'old'}`;  // 修复字符串拼接
    const discount = discountRules[key] || 1.0;  // 默认无折扣
    return originalPrice * discount;
}

// 使用示例
console.log(calculatePrice('vip', true, 100));    // VIP新用户: 100*0.8 = 80
console.log(calculatePrice('vip', false, 100));   // VIP老用户: 100*0.9 = 90
console.log(calculatePrice('normal', true, 100)); // 普通新用户: 100*0.95 = 95
console.log(calculatePrice('normal', false, 100));// 普通老用户: 100*1.0 = 100
console.log(calculatePrice('invalid', true, 100));// 未知类型: 100*1.0 = 100 (默认)

性能对比

让我们来看看性能差异:

// 测试数据
const testCases = Array.from({ length: 10000 }, () =>
  ['loading', 'success', 'error', 'timeout'][Math.floor(Math.random() * 4)]
);

// Switch 版本
function switchVersion(status) {
 switch (status) {
    case 'loading': return '正在加载...';
    case 'success': return '操作成功!';
    case 'error': return '操作失败,请重试';
    case 'timeout': return '请求超时';
    default: return '未知状态';
  }
}

// 对象映射版本
const objectMapping = {
 loading: '正在加载...',
 success: '操作成功!',
 error: '操作失败,请重试',
 timeout: '请求超时'
};

function objectVersion(status) {
 return objectMapping[status] || '未知状态';
}

// 性能测试
console.time('Switch版本');
testCases.forEach(switchVersion);
console.timeEnd('Switch版本');

console.time('对象映射版本');
testCases.forEach(objectVersion);
console.timeEnd('对象映射版本');

通常情况下,对象映射的性能会略优于 switch 语句,特别是在分支较多的情况下。

当然,这并不意味着要完全抛弃 switch 语句。在选择使用哪种方案时,应该根据具体的业务场景和需求来决定。对于简单的映射关系,对象映射是更好的选择;对于复杂的条件判断和控制流,switch 语句可能更加合适。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言