前端代码重构

什么是重构、何时重构、常见重构手法

问题

谈谈你对重构的理解。

解答

什么是重构

重构是在不改变代码外部行为的前提下,改善代码内部结构的过程。目的是让代码更易读、更易维护、更易扩展。

何时需要重构

  1. 添加新功能前 - 先整理现有代码,让新功能更容易加入
  2. 修复 Bug 时 - 理解代码过程中顺手改进
  3. Code Review 时 - 发现问题及时优化
  4. 代码有”坏味道”时 - 重复代码、过长函数、过大类等

常见重构手法

1. 提取函数

// 重构前
function printOrder(order) {
  console.log('=== 订单详情 ===');
  console.log(`商品: ${order.name}`);
  console.log(`数量: ${order.quantity}`);
  console.log(`单价: ${order.price}`);
  console.log(`总价: ${order.quantity * order.price}`);
  console.log('================');
}

// 重构后:提取计算逻辑
function calculateTotal(order) {
  return order.quantity * order.price;
}

function printOrder(order) {
  console.log('=== 订单详情 ===');
  console.log(`商品: ${order.name}`);
  console.log(`数量: ${order.quantity}`);
  console.log(`单价: ${order.price}`);
  console.log(`总价: ${calculateTotal(order)}`);
  console.log('================');
}

2. 用对象代替多个参数

// 重构前:参数过多,难以记忆顺序
function createUser(name, age, email, phone, address, role) {
  // ...
}

// 重构后:使用配置对象
function createUser({ name, age, email, phone, address, role }) {
  // ...
}

createUser({
  name: '张三',
  age: 25,
  email: 'test@example.com',
  phone: '13800138000',
  address: '北京',
  role: 'admin'
});

3. 用 Map 替代条件分支

// 重构前:冗长的 if-else
function getStatusText(status) {
  if (status === 0) return '待支付';
  if (status === 1) return '已支付';
  if (status === 2) return '已发货';
  if (status === 3) return '已完成';
  if (status === 4) return '已取消';
  return '未知状态';
}

// 重构后:使用映射表
const STATUS_MAP = {
  0: '待支付',
  1: '已支付',
  2: '已发货',
  3: '已完成',
  4: '已取消'
};

function getStatusText(status) {
  return STATUS_MAP[status] ?? '未知状态';
}

4. 提取组件(React 示例)

// 重构前:组件过大
function UserPage() {
  return (
    <div>
      <div className="header">
        <img src={user.avatar} alt="头像" />
        <span>{user.name}</span>
        <span>{user.role}</span>
      </div>
      <div className="content">
        {/* 大量内容 */}
      </div>
    </div>
  );
}

// 重构后:拆分子组件
function UserHeader({ user }) {
  return (
    <div className="header">
      <img src={user.avatar} alt="头像" />
      <span>{user.name}</span>
      <span>{user.role}</span>
    </div>
  );
}

function UserPage() {
  return (
    <div>
      <UserHeader user={user} />
      <UserContent />
    </div>
  );
}

5. 用 Early Return 简化逻辑

// 重构前:嵌套过深
function processData(data) {
  if (data) {
    if (data.list) {
      if (data.list.length > 0) {
        return data.list.map(item => item.name);
      }
    }
  }
  return [];
}

// 重构后:提前返回
function processData(data) {
  if (!data) return [];
  if (!data.list) return [];
  if (data.list.length === 0) return [];
  
  return data.list.map(item => item.name);
}

重构原则

  1. 小步前进 - 每次只改一点,频繁测试
  2. 保持测试通过 - 重构不应破坏现有功能
  3. 先写测试 - 有测试才敢放心改
  4. 不要同时重构和加功能 - 一次只做一件事

关键点

  • 重构是改善代码结构,不改变外部行为
  • 识别代码坏味道:重复、过长、嵌套深、参数多
  • 常用手法:提取函数、提取组件、简化条件、Early Return
  • 小步重构,每次改动后确保测试通过
  • 重构和添加功能要分开进行