万字长文助力你写出不可维护的代码,不被裁员!

1,395 阅读11分钟

前言

生活很无奈,无论在大厂,还是小厂,都是很难,找工作困难,裁员盛行,虽出此下策。 望更多有志之士,在评论区给出更多的不可维护代码的示例

然后做一首现代小诗送给各位大佬

诗名:当代牛马

生活真无奈,工作把心掏

加班当牛马,PUA不停歇

不爽就拍桌,看我愁眉皱

裁员还家去,双双告别愁

打工人,打工魂,
打工都是人上人!


1. 晦涩或不一致的命名

头疼代码示例:

function a(b, c) {
  const d = b + c;
  return d * 42;
}

const data1 = a(5, 10);

最佳实践:

function calculateTotalCost(price, quantity) {
  const subtotal = price + quantity;
  return subtotal * 42; // 42 是税率系数,可以进一步提取为常量
}

const totalCost = calculateTotalCost(5, 10);

2. 长函数或嵌套过深的代码

头疼代码示例:

function processOrder(order) {
  if (order) {
    if (order.items) {
      order.items.forEach(item => {
        if (item.quantity > 0) {
          if (item.price > 0) {
            console.log(`Processing item: ${item.name}`);
            // More logic here...
          }
        }
      });
    }
  }
}

最佳实践:

function processOrder(order) {
  if (!order || !order.items) return;

  order.items.forEach(processItem);
}

function processItem(item) {
  if (isItemValid(item)) {
    console.log(`Processing item: ${item.name}`);
    // More fuck here...
  }
}

function isItemValid(item) {
  return item.quantity > 0 && item.price > 0;
}

3. 魔法数和硬编码

头疼代码示例:

const discount = price * 0.08; // 0.08 是什么含义?
const tax = price * 0.15; // 0.15 是什么含义?

最佳实践:

const DISCOUNT_RATE = 0.08;
const TAX_RATE = 0.15;

const discount = price * DISCOUNT_RATE;
const tax = price * TAX_RATE;

4. 滥用或混用不同编程风格

头疼代码示例:

// 面向对象风格
class User {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    return `Hello, ${this.name}`;
  }
}

// 函数式风格
const greetUser = (user) => `Hello, ${user.name}`;

最佳实践: 选择一种风格来实现所有的功能。假如选择函数式风格:

const createUser = (name) => ({
  name,
  greet() {
    return `Hello, ${this.name}`;
  }
});

5. 隐含依赖关系

头疼代码示例:

// moduleA.js
import { sharedConfig } from './sharedConfig';

export function initialize() {
  console.log(sharedConfig.apiUrl);
}

// moduleB.js
import { sharedConfig } from './sharedConfig';

export function configure() {
  sharedConfig.apiUrl = 'https://new-api.com';
}

最佳实践: 明确传递依赖,避免模块间隐含的依赖。

// moduleA.js
export function initialize(config) {
  console.log(config.apiUrl);
}

// moduleB.js
import { initialize } from './moduleA';

const config = { apiUrl: 'https://new-api.com' };
initialize(config);

6. 误导性注释或缺少注释

头疼代码示例:

// TODO: 添加安全检查
function validateUser(user) {
  // 现在只返回true
  return true;
}

最佳实践: 添加清晰、准确的注释,并定期更新以确保信息正确。

/**
 * 通过检查用户对象的属性来验证用户对象。
 * TODO: 根据需求实现实际的验证逻辑。
 * @param {Object} user - 要验证的用户对象。
 * @returns {boolean} - 用户是否有效。
 */
function validateUser(user) {
  return true; // 占位符,要实现的实际验证逻辑
}

7. 规避标准库或常用工具

头疼代码示例:

// 自己实现一个简单的深拷贝函数,可能有缺陷
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

最佳实践: 使用成熟的库,如 Lodash 或 structuredClone(原生支持),保证深拷贝的可靠性。

import cloneDeep from 'lodash/cloneDeep';

const newObj = cloneDeep(obj);

8. 不进行代码结构优化和重构

头疼代码示例: 随着时间的推移,代码变得臃肿,难以理解:

function processOrder(order) {
  // 处理订单的逻辑
  if (order.status === 'new') {
    // 处理新订单
  } else if (order.status === 'in_progress') {
    // 处理进行中的订单
  } else if (order.status === 'completed') {
    // 处理完成的订单
  }
  
  // 还有许多其他的逻辑,混杂在一起
}

最佳实践: 定期进行代码重构,确保代码清晰、简洁。

function processOrder(order) {
  switch (order.status) {
    case 'new':
      handleNewOrder(order);
      break;
    case 'in_progress':
      handleInProgressOrder(order);
      break;
    case 'completed':
      handleCompletedOrder(order);
      break;
    default:
      console.error('未知订单状态');
  }
}

function handleNewOrder(order) { /* ... */ }
function handleInProgressOrder(order) { /* ... */ }
function handleCompletedOrder(order) { /* ... */ }

9. 过度使用全局变量

头疼代码示例: 使用全局变量可能会导致难以追踪的状态变化,使代码的可维护性和可预测性大大降低。

let userRole = 'admin';

function setRole(role) {
  userRole = role;
}

function performAction() {
  if (userRole === 'admin') {
    // 执行管理员操作
  } else {
    // 执行普通用户操作
  }
}

最佳实践: 避免全局变量,使用函数参数传递,或封装在模块中控制变量范围。

function performAction(role) {
  if (role === 'admin') {
    // 执行管理员操作
  } else {
    // 执行普通用户操作
  }
}
performAction('admin');

10. 使用过多的嵌套条件语句

头疼代码示例: 深层嵌套的条件语句会导致代码结构复杂化,使得代码难以理解和维护。

function handleRequest(user) {
  if (user) {
    if (user.isActive) {
      if (user.hasPermission) {
        // 处理用户请求
      } else {
        console.log('无权限');
      }
    } else {
      console.log('用户不活跃');
    }
  } else {
    console.log('用户不存在');
  }
}

最佳实践: 使用早期返回来减少嵌套,让代码逻辑更加清晰。

function handleRequest(user) {
  if (!user) return console.log('用户不存在');
  if (!user.isActive) return console.log('用户不活跃');
  if (!user.hasPermission) return console.log('无权限');
  
  // 处理用户请求
}

11. 忽视错误处理

头疼代码示例: 不进行错误处理,直接假设操作总是会成功,容易导致运行时错误。

function fetchData(url) {
  return fetch(url).then(response => response.json());
}

最佳实践: 添加错误处理机制,以便在出错时能够合理应对,提供用户友好的反馈。

async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) throw new Error('网络请求失败');
    return await response.json();
  } catch (error) {
    console.error('数据获取失败:', error);
    // 可以返回一个默认值或通知用户错误
  }
}

12. 不必要的深层对象访问

头疼代码示例: 直接访问深层嵌套的对象属性会增加代码的脆弱性,如果某层属性缺失则会导致错误。

console.log(user.profile.details.address.city);

最佳实践: 使用可选链(optional chaining)和空值合并操作符来确保安全访问。

console.log(user?.profile?.details?.address?.city ?? '未知城市');

13. 在循环中频繁操作 DOM

头疼代码示例: 频繁的 DOM 操作会大幅降低性能,特别是在循环中直接操作 DOM。

const items = ['item1', 'item2', 'item3'];
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  document.getElementById('list').appendChild(li);
});

最佳实践: 将所有元素构建完成后,再一次性添加到 DOM 中,减少重绘和重排。

const items = ['item1', 'item2', 'item3'];
const fragment = document.createDocumentFragment();
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  fragment.appendChild(li);
});
document.getElementById('list').appendChild(fragment);

14. 不使用事件委托

头疼代码示例: 为多个元素添加相同的事件处理函数会增加内存消耗和事件处理的开销。

document.querySelectorAll('.item').forEach(item => {
  item.addEventListener('click', () => {
    console.log('Item clicked');
  });
});

最佳实践: 使用事件委托,将事件绑定到父元素上,通过事件目标识别点击的子元素。

document.getElementById('container').addEventListener('click', event => {
  if (event.target.classList.contains('item')) {
    console.log('Item clicked');
  }
});

15. 过度使用回调函数导致“回调地狱”

头疼代码示例: 多层嵌套的回调函数(“回调地狱”)让代码难以维护、调试和理解。

fetch(url1, data => {
  fetch(url2, data => {
    fetch(url3, data => {
      console.log('全部完成');
    });
  });
});

最佳实践: 使用 async/await 或 Promise 链将代码展平,提升可读性。

async function fetchData() {
  await fetch(url1);
  await fetch(url2);
  await fetch(url3);
  console.log('全部完成');
}
fetchData();

16. 将样式硬编码在 JavaScript 中

头疼代码示例: 直接在 JavaScript 中定义样式可能会导致样式难以管理和维护。

element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';
element.style.padding = '10px';

最佳实践: 将样式分离到 CSS 文件中,并在 JavaScript 中使用类名控制样式。

/* styles.css */
.highlight {
  background-color: blue;
  font-size: 16px;
  padding: 10px;
}
element.classList.add('highlight');

17. 忽视模块化开发

头疼代码示例: 所有代码都放在一个文件中,难以维护、扩展或复用。

function fetchData() { /* ... */ }
function renderData() { /* ... */ }
function handleClick() { /* ... */ }
// 所有功能函数都在一个文件中

最佳实践: 将代码模块化,根据功能拆分为多个文件,使代码易于维护和复用。

// fetchData.js
export function fetchData() { /* ... */ }

// renderData.js
export function renderData() { /* ... */ }

// handleClick.js
export function handleClick() { /* ... */ }

18. 使用过多的条件分支而不简化逻辑

头疼代码示例: 大量的条件分支导致代码难以阅读和维护。

function getDiscount(userType) {
  if (userType === 'guest') return 0;
  if (userType === 'member') return 0.1;
  if (userType === 'vip') return 0.2;
  if (userType === 'super-vip') return 0.3;
  return 0;
}

最佳实践: 使用对象字面量或映射表来简化条件分支。

const discountRates = {
  guest: 0,
  member: 0.1,
  vip: 0.2,
  'super-vip': 0.3,
};

function getDiscount(userType) {
  return discountRates[userType] || 0;
}

上框架

1. Vue 中不可维护的代码示例

示例 1:所有逻辑都写在一个组件中

头疼代码示例: 将所有逻辑都写在一个 Vue 组件中,使得组件臃肿、难以维护。

<template>
  <div>
    <button @click="incrementCounter">增加计数</button>
    <p>{{ counter }}</p>
    <button @click="fetchData">获取数据</button>
    <p v-if="data">{{ data }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0,
      data: null,
    };
  },
  methods: {
    incrementCounter() {
      this.counter += 1;
    },
    fetchData() {
      fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => {
          this.data = data;
        })
        .catch(error => console.error(error));
    },
  },
};
</script>

问题:这个组件包含计数器和数据获取的逻辑,混合了不同功能,使代码难以复用。

最佳实践:将功能拆分为多个组件或使用组合函数(Vue 3 中的 composition API)来分离逻辑。

<!-- CounterComponent.vue -->
<template>
  <div>
    <button @click="incrementCounter">增加计数</button>
    <p>{{ counter }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0,
    };
  },
  methods: {
    incrementCounter() {
      this.counter += 1;
    },
  },
};
</script>
<!-- FetchDataComponent.vue -->
<template>
  <div>
    <button @click="fetchData">获取数据</button>
    <p v-if="data">{{ data }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: null,
    };
  },
  methods: {
    fetchData() {
      fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => {
          this.data = data;
        })
        .catch(error => console.error(error));
    },
  },
};
</script>

示例 2:过度使用 $emit$on 进行父子通信

头疼代码示例: 通过 $emit$on 频繁进行父子组件通信,逻辑难以追踪。

<!-- ChildComponent.vue -->
<template>
  <button @click="handleClick">点击</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('some-event', 'data');
    },
  },
};
</script>

<!-- ParentComponent.vue -->
<template>
  <ChildComponent @some-event="handleEvent" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  methods: {
    handleEvent(data) {
      console.log('接收到事件', data);
    },
  },
};
</script>

问题:如果有多个嵌套层级或事件较多时,代码变得难以维护和调试。

最佳实践:使用 Vuex 进行状态管理,减少不必要的事件传递。

示例 3:滥用混入 (mixins)

头疼代码示例: 混入 (mixins) 在 Vue 中用来共享逻辑,但如果过度使用,容易导致依赖不清晰,且逻辑难以追踪,尤其是在多个混入重叠时。

// mixin1.js
export default {
  data() {
    return {
      message: 'Hello from mixin1',
    };
  },
};

// mixin2.js
export default {
  data() {
    return {
      message: 'Hello from mixin2',
    };
  },
};

// MyComponent.vue
<template>
  <div>{{ message }}</div>
</template>

<script>
import mixin1 from './mixin1';
import mixin2 from './mixin2';

export default {
  mixins: [mixin1, mixin2],
};
</script>

问题:多个混入会相互覆盖相同的属性(如 message),导致逻辑混乱,难以调试。

最佳实践:使用组合式 API (Composition API) 替代混入,将逻辑封装在自定义的 composition 函数中,使代码结构更加清晰。

// useMessage.js
import { ref } from 'vue';

export default function useMessage() {
  const message = ref('Hello from custom hook');
  return { message };
}

// MyComponent.vue
<template>
  <div>{{ message }}</div>
</template>

<script>
import useMessage from './useMessage';

export default {
  setup() {
    const { message } = useMessage();
    return { message };
  },
};
</script>

示例 4:使用过多的 v-if 条件渲染导致混乱

头疼代码示例: 多个 v-ifv-else-if 条件堆叠在一起,导致代码难以理解。

<template>
  <div>
    <p v-if="status === 'loading'">加载中...</p>
    <p v-else-if="status === 'error'">加载失败</p>
    <p v-else-if="status === 'empty'">暂无数据</p>
    <p v-else>内容加载完成</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      status: 'loading',
    };
  },
};
</script>

问题:多个条件语句让代码阅读和维护变得困难。

最佳实践:使用计算属性返回要显示的内容,并在模板中只使用一个条件表达式。

<template>
  <div>
    <p>{{ statusMessage }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      status: 'loading',
    };
  },
  computed: {
    statusMessage() {
      switch (this.status) {
        case 'loading':
          return '加载中...';
        case 'error':
          return '加载失败';
        case 'empty':
          return '暂无数据';
        default:
          return '内容加载完成';
      }
    },
  },
};
</script>

示例 5:过度依赖 $refs 操作 DOM

头疼代码示例: 在 Vue 中,使用 $refs 操作 DOM 是一种反模式,尤其是当操作非常频繁时,代码会变得难以维护。

<template>
  <div ref="container">
    <button @click="changeBackgroundColor">改变背景颜色</button>
  </div>
</template>

<script>
export default {
  methods: {
    changeBackgroundColor() {
      this.$refs.container.style.backgroundColor = 'blue';
    },
  },
};
</script>

问题:过度依赖 $refs 操作 DOM 会导致 Vue 的数据驱动特性失去意义,代码不符合响应式的思想。

最佳实践:使用 Vue 的响应式数据绑定和样式动态绑定。

<template>
  <div :style="{ backgroundColor: backgroundColor }">
    <button @click="changeBackgroundColor">改变背景颜色</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      backgroundColor: 'white',
    };
  },
  methods: {
    changeBackgroundColor() {
      this.backgroundColor = 'blue';
    },
  },
};
</script>

示例 6:在 v-for 中使用索引作为 key

头疼代码示例: 在 Vue 中使用 v-for 时,使用索引作为 key 值会导致错误的渲染或组件更新行为。

<template>
  <ul>
    <li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
  </ul>
</template>

问题:当列表项顺序发生改变时,Vue 可能无法正确跟踪每一项的状态,从而引发渲染问题。

最佳实践:使用唯一的标识符(如 id)作为 key 值,确保列表项在更新时正确渲染。

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

2. React 中不可维护的代码示例

示例 1:逻辑混杂在组件中,未拆分成自定义 Hook

头疼代码示例:将逻辑都写在组件中,导致代码臃肿,不易维护。

import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [counter, setCounter] = useState(0);
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data))
      .catch(error => console.error(error));
  }, []);

  return (
    <div>
      <button onClick={() => setCounter(counter + 1)}>增加计数</button>
      <p>{counter}</p>
      {data && <p>{data}</p>}
    </div>
  );
}

问题:组件同时包含计数逻辑和数据获取逻辑,导致代码复杂,难以复用。

最佳实践:将逻辑提取到自定义 Hook 中,使代码更清晰、易维护。

import React, { useState } from 'react';
import useFetchData from './useFetchData';

function MyComponent() {
  const [counter, setCounter] = useState(0);
  const data = useFetchData('https://api.example.com/data');

  return (
    <div>
      <button onClick={() => setCounter(counter + 1)}>增加计数</button>
      <p>{counter}</p>
      {data && <p>{data}</p>}
    </div>
  );
}

// useFetchData.js
import { useState, useEffect } from 'react';

export default function useFetchData(url) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => setData(data))
      .catch(error => console.error(error));
  }, [url]);

  return data;
}

示例 2:过度嵌套和条件渲染

头疼代码示例: 在组件中使用嵌套过深的条件渲染,导致代码难以阅读和维护。

import React from 'react';

function MyComponent({ user }) {
  return (
    <div>
      {user ? (
        user.isAdmin ? (
          <p>欢迎管理员</p>
        ) : (
          <p>欢迎用户</p>
        )
      ) : (
        <p>请登录</p>
      )}
    </div>
  );
}

问题:嵌套的条件语句让代码难以阅读和维护。

最佳实践:将条件逻辑提取为变量或使用早期返回。

import React from 'react';

function MyComponent({ user }) {
  if (!user) return <p>请登录</p>;
  return <p>欢迎{user.isAdmin ? '管理员' : '用户'}</p>;
}

示例 3:未优化的 useEffect 依赖导致重复渲染

头疼代码示例: 未正确设置 useEffect 的依赖项,导致组件在每次渲染时都重复执行该副作用。

import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('副作用执行');
    // 模拟一些数据获取
  }); // 没有设置依赖项

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

问题:由于没有设置依赖项,useEffect 会在每次渲染时执行,导致不必要的重复操作。

最佳实践:确保在 useEffect 中正确设置依赖项,避免不必要的重复渲染。

useEffect(() => {
  console.log('副作用执行');
  // 模拟一些数据获取
}, []); // 空数组表示只在组件挂载时执行一次

示例 4:直接操作 DOM,未使用 ref

头疼代码示例: 直接使用 document.getElementByIdquerySelector 操作 DOM,违背了 React 的虚拟 DOM 和组件化思想。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    document.getElementById('my-element').style.backgroundColor = 'blue';
  }, []);

  return <div id="my-element">Hello World</div>;
}

问题:这种写法会导致代码不符合 React 的操作模式,不仅难以维护,还可能引发意外的渲染问题。

最佳实践:使用 React 的 ref 来操作 DOM 元素,保证与 React 的渲染流程一致。

import React, { useEffect, useRef } from 'react';

function MyComponent() {
  const elementRef = useRef(null);

  useEffect(() => {
    if (elementRef.current) {
      elementRef.current.style.backgroundColor = 'blue';
    }
  }, []);

  return <div ref={elementRef}>Hello World</div>;
}

示例 5:在 JSX 中编写过多的逻辑表达式

头疼代码示例: 在 JSX 中嵌入复杂的逻辑表达式,导致代码可读性差。

import React from 'react';

function MyComponent({ items }) {
  return (
    <div>
      {items.length > 0 ? (
        items.map((item, index) => (
          <p key={index}>{item.active ? item.name : 'Inactive'}</p>
        ))
      ) : (
        <p>No items available</p>
      )}
    </div>
  );
}

问题:在 JSX 中处理复杂逻辑,增加了代码的阅读难度,降低了可维护性。

最佳实践:将复杂逻辑提取到渲染前的函数中,使 JSX 更加简洁。

import React from 'react';

function MyComponent({ items }) {
  const renderItems = () => {
    if (items.length === 0) return <p>No items available</p>;

    return items.map((item, index) => (
      <p key={index}>{item.active ? item.name : 'Inactive'}</p>
    ));
  };

  return <div>{renderItems()}</div>;
}

示例 6:未清理副作用导致的内存泄漏

头疼代码示例: 在使用 useEffect 时忘记清理副作用,导致内存泄漏或意外行为。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Timer running...');
    }, 1000);
  }, []);

  return <div>My Component</div>;
}

问题setInterval 没有清理,组件卸载后定时器仍会运行,导致内存泄漏。

最佳实践:在 useEffect 中返回一个清理函数,确保组件卸载时清理副作用。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Timer running...');
    }, 1000);

    return () => clearInterval(timer); // 清理定时器
  }, []);

  return <div>My Component</div>;
}

示例 7:在 useEffect 中使用外部状态却未添加为依赖

头疼代码示例:useEffect 中使用了组件外部的状态(props 或 state),但未将其添加到依赖项中,导致副作用逻辑不准确。

import React, { useState, useEffect } from 'react';

function MyComponent({ propValue }) {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('Prop value is:', propValue);
  }, []); // propValue 未被添加为依赖项
}

问题:未正确添加依赖项时,propValue 的变更不会触发 useEffect 的重新执行,导致逻辑错误。

最佳实践:将外部状态添加到依赖项数组中,确保 useEffect 能正确响应状态的变化。

useEffect(() => {
  console.log('Prop value is:', propValue);
}, [propValue]); // 添加 propValue 作为依赖项

示例 8:滥用 useState,而不是使用 useReducer

头疼代码示例: 在管理复杂状态时,使用 useState 会导致代码变得冗长,状态管理混乱。

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);

  const increment = () => setCount(count + step);
  const decrement = () => setCount(count - step);

  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}

问题:在状态管理复杂的情况下,使用多个 useState 会导致代码混乱,难以维护。

最佳实践:使用 useReducer 管理复杂状态,以清晰地组织更新逻辑。

import React, { useReducer } from 'react';

const initialState = { count: 0, step: 1 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + state.step };
    case 'decrement':
      return { ...state, count: state.count - state.step };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <span>{state.count}</span>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </div>
  );
}

示例 9:直接在 JSX 中编写样式

头疼代码示例: 在 JSX 中直接编写样式对象,导致代码臃肿且难以阅读。

function MyComponent() {
  return (
    <div
      style={{
        backgroundColor: 'blue',
        color: 'white',
        padding: '10px',
        borderRadius: '5px',
      }}
    >
      Hello World
    </div>
  );
}

问题:样式对象混在组件代码中,降低了代码的可读性和可维护性。

最佳实践:将样式对象抽离到单独的变量中,或使用 CSS-in-JS 方案。

const styles = {
  container: {
    backgroundColor: 'blue',
    color: 'white',
    padding: '10px',
    borderRadius: '5px',
  },
};

function MyComponent() {
  return <div style={styles.container}>Hello World</div>;
}

示例 10:无意义的依赖项在 useEffect 中造成重复渲染

头疼代码示例:useEffect 中添加无意义的依赖项,导致不必要的重复渲染。

import React, { useState, useEffect } from 'react';

function MyComponent({ user }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(`https://api.example.com/user/${user.id}`)
      .then(response => response.json())
      .then(data => setData(data));
  }, [data]); // 错误:data 应该不在依赖项中
}

问题:将 data 作为依赖项会导致 useEffect 每次执行时都重新运行,使得组件无限重新渲染。

最佳实践:仅添加必要的依赖项,避免不必要的重复渲染。

useEffect(() => {
  fetch(`https://api.example.com/user/${user.id}`)
    .then(response => response.json())
    .then(data => setData(data));
}, [user.id]); // 仅依赖 user.id

示例 11:过度使用内联函数导致性能问题

头疼代码示例: 在 JSX 中直接定义内联函数,导致每次渲染时函数重新创建,可能影响性能。

function MyComponent({ onClick }) {
  return (
    <button onClick={() => onClick('clicked')}>Click Me</button>
  );
}

问题:在每次渲染时,内联函数都会重新创建,特别是在子组件较多的情况下,会影响性能。

最佳实践:将函数提取为组件的成员函数,减少函数的重新创建。

function MyComponent({ onClick }) {
  const handleClick = () => onClick('clicked');

  return <button onClick={handleClick}>Click Me</button>;
}

综合示例:Vue 和 React 共同的反模式

示例 12:使用硬编码值而不是配置或常量

头疼代码示例: 在代码中直接使用硬编码的值,使得代码难以更新和维护。

// 反模式:直接使用硬编码值
const TAX_RATE = 0.08;
function calculatePrice(price) {
  return price + price * 0.08; // 硬编码税率
}

问题:硬编码值可能会分散在代码各处,修改时不便,还可能导致不一致。

最佳实践:将所有常量提取到配置文件或单独的常量模块中,集中管理。

// config.js
export const TAX_RATE = 0.08;

// 使用时
import { TAX_RATE } from './config';
function calculatePrice(price) {
  return price + price * TAX_RATE;
}

示例 13:滥用 try-catch 捕获

头疼代码示例: 在每个可能出错的地方都添加 try-catch,导致代码冗余和难以维护。

try {
  const result1 = await fetchData1();
} catch (error) {
  console.error(error);
}

try {
  const result2 = await fetchData2();
} catch (error) {
  console.error(error);
}

问题:大量的 try-catch 会让代码臃肿,不利于错误管理。

最佳实践:将错误处理逻辑封装在统一的错误处理函数中,集中管理。

async function safeFetch(fetchFn) {
  try {
    return await fetchFn();
  } catch (error) {
    console.error('Error:', error);
    return null;
  }
}

// 使用时
const result1 = await safeFetch(fetchData1);
const result2 = await safeFetch(fetchData2);

结束

  • 加油,铁子们,希望大家都能升职加薪,技术交流,面试交流互助:843655240

传送门