四年前端被问 Code Review90人只看得懂空格和命名

CR 只看格式命名,是初级信号。完整 CR 有 5 层:格式、语法逻辑、异常副作用、架构可维护性、线上性能安全。答到第三层才算合格。

一个问题就能分层

上周面了个 4 年前端。简历写着"熟悉团队代码规范,经常参与 CodeReview"。

我问:你们做 CR 主要看什么?

他脱口而出:格式对不对,命名好不好看。

我追问:如果现在让你做一次完整的 CodeReview,从业务逻辑、边界处理到可维护性、线上风险,你能说出多少个检查维度?不同缺陷的严重优先级怎么区分?

他卡住了。

很多前端以为 Code Review 就是改空格和变量命名。到 2026 年,代码规范和 CR 早不只是格式化代码,这是工程能力的分水岭。

我一般用 5 个层面测人。第三层算合格,第四第五层是高级开发和普通开发的差距。

五层全景

先把全景摆出来,后面逐层拆。

flowchart TD A[提交 PR 进入评审] --> B[L1 基础格式规范] B --> C[L2 语法与业务逻辑] C --> D[L3 业务与异常处理] D --> E[L4 架构与可维护性] E --> F[L5 线上性能与安全] F --> G{缺陷分级} G -->|P0 阻断| H[打回修改] G -->|P1 P2 记录 issue| I[有条件合并] G -->|P3 建议| I

L1 格式规范:别把工具活当技术活

命名、缩进、分号、引号统一、禁止未定义变量------最没技术含量,也最容易被误当成 CR 的全部。

真正的追问在后面:同样是 ESLint 报错,哪些必须阻断合并,哪些只做警告提示?自动 Fix 过后,会不会隐藏真正的 bug?

看配置就明白:

js 复制代码
// .eslintrc.cjs ------ 区分"阻断"和"提示"
module.exports = {
  rules: {
    'no-unused-vars': 'error',   // 阻断:可能是有副作用的导入被误删
    'no-undef': 'error',         // 阻断:运行时必炸
    quotes: ['warn', 'single'],  // 提示:Prettier 的事,不该占用人注意力
    semi: ['warn', 'always'],
    'max-len': 'off',            // 直接关掉,交给格式化工具
  },
};

自动 Fix 最典型的坑:import './polyfill' 被判定为未使用变量删掉,构建产物在低版本浏览器直接白屏。格式问题交给工具,人的注意力留给工具看不见的东西。

L2 语法与业务逻辑:三年经验也常踩空

这一层考代码本身的正确性,检查点密集:

  • 类型是否完备,有没有漏掉边界判断
  • 参数校验:入参为空、undefined、null 场景是否都兜住
  • 重复代码识别:复制粘贴出来的业务逻辑,该不该抽公共工具函数
  • 副作用问题:函数是否纯函数,有没有随意修改入参对象
  • 魔法数字与常量:if (status === 3) 这种散落各处的硬编码

入参修改是最常见的翻车点:

ts 复制代码
// bad:改了入参对象,调用方数据被污染,还漏了兜底
function normalizeUser(user: User) {
  user.name = user.name.trim();
  if (user.age > 18) user.adult = true;
  return user;
}

// good:不改入参,返回新对象,边界先兜住
function normalizeUser(input: UserInput): User {
  const name = input?.name?.trim() ?? '';
  const age = Number.isFinite(input?.age) ? input.age : 0;
  return { ...input, name, age, adult: age >= 18 };
}

注释也得有判断力。必须写的是"为什么这么做"(踩过的坑、绕开的兼容性),不是"做了什么"。// 把 count 加一 这种复述代码的注释,删掉比留着强;注释掉的死代码更是直接删。

L3 异常与副作用:这里才见真功夫

到这一层,评审的是"这段代码上线会不会出事"。

接口请求有没有补异常,失败之后页面如何降级?权限埋点逻辑会不会漏写多写?if-else 嵌套超过四层、条件分支漏了 default,都是典型漏网之鱼。

状态更新风险。组件状态修改造成死循环渲染,是前端特有的一类 bug:

flowchart TD A[组件 render] --> B[useEffect 执行] B --> C[setState 更新状态] C --> D[状态变化触发重渲染] D --> A D -.->|依赖数组缺少该项| E[无限循环 页面卡死]

副作用清理同理------定时器、事件监听、请求,组件销毁时统统要释放,否则就是内存泄漏。

tsx 复制代码
// bad:请求失败无兜底,定时器不清理,卸载后照样 setState
useEffect(() => {
  fetch('/api/list').then(r => r.json()).then(setList);
  const timer = setInterval(poll, 3000);
}, []);

// good:中断 + 存活标记 + 清理函数
useEffect(() => {
  const ac = new AbortController();
  let alive = true;
  fetch('/api/list', { signal: ac.signal })
    .then(r => { if (!r.ok) throw new Error(`HTTP $${r.status}`); return r.json(); })
    .then(d => { if (alive) setList(d); })
    .catch(e => { if (alive) setError(e.message); });
  const timer = setInterval(poll, 3000);
  return () => { alive = false; ac.abort(); clearInterval(timer); };
}, []);

能在这个层面拦下问题的评审者,价值远超"改格式"。

L4 架构与可维护性:高级开发的分水岭

  • 模块职责划分:单个文件、单个函数是不是职责过重
  • 依赖引入:有没有引入冗余包,有没有循环依赖
  • 组件设计:传参是否合理,Props 有没有做约束,是否存在过度封装
  • 复用逻辑:hooks 和工具函数设计得够不够通用,有没有写一堆一次性临时逻辑
  • 兼容性:新 API 有没有降级方案,目标浏览器环境评估过没有

Props 裸奔是最典型的:

tsx 复制代码
// bad:传错类型运行时才炸
function Chart({ data, type, config }) { /* ... */ }

// good:联合类型把非法值挡在编译期
type ChartProps = {
  data: number[];
  type: 'line' | 'bar';
  config?: Partial<ChartConfig>;
};
function Chart({ data, type, config = {} }: ChartProps) { /* ... */ }

L5 性能与安全:事故防线

最后一层,触及线上事故底线。

大数据列表一次性渲染卡死页面、不必要的重渲染、死循环------性能问题这里过一遍。

XSS 更直接:用户输入直接塞进 innerHTML,等于把站点交给攻击者。

ts 复制代码
// bad:直接渲染用户输入
el.innerHTML = `<div>$${comment}</div>`;

// good:要么用 textContent,要么必须过滤
el.textContent = comment;
// 富文本场景
el.innerHTML = DOMPurify.sanitize(comment, { ALLOWED_TAGS: ['b', 'i', 'a'] });

还有两件常被忽略的事:密钥有没有写死在前端代码里(打包后的 dist 目录一 grep 就出来);上线出问题,这段改动能不能快速回滚------一个 PR 混进五个不相关的功能,revert 就是灾难。

新增逻辑有没有补对应的单元测试用例,也在这层问。这个才叫专业。

缺陷优先级:说不出来就是没判断力

说不出优先级,等于没有判断力。我的分法:

级别 判定标准 处理方式
P0 阻断 XSS、内存泄漏、死循环、密钥硬编码 必须改完再合
P1 严重 逻辑漏洞、异常未处理导致功能不可用 本次迭代内修复
P2 一般 重复代码、职责过重、命名有误导性 记录 issue,可先合
P3 建议 格式、注释风格、个人偏好 交给 ESLint 自动修复

关键不是分级本身,而是你知道哪一类问题一旦漏掉,代价是凌晨三点的线上事故。

写在最后

同样一份 CR,有人只看格式排版,有人能提前拦住线上事故。这就是技术深度。

我反问候选人:你现在觉得 CodeReview 真的就只是改改代码格式吗?

你们做 CodeReview 踩过最坑的问题是什么?是某个被放过去的 useEffect,还是一次让整个模块回滚的误合并?评论区聊聊。

有用的话点个赞。

相关推荐
garmin Chen1 小时前
MySQL精简面试题
数据库·后端·mysql·面试
IPdodo_1 小时前
curl 如何测试代理 IP?HTTP、SOCKS5 与认证参数示例
前端·网络·python·https·网络调试
做前端的娜娜子1 小时前
施工蓝图:vite.config.js —— 项目的指挥中心
前端·react native·vite
宸翰1 小时前
解决uni-app 中 SVG 图片在 iOS 端显示模糊问题
前端·uni-app
数据掘金1 小时前
第三方 SDK 集体故障时,你的 App 会怎样?可落地的监控与降级方案
前端
AI分享猿1 小时前
UI设计Prompt系列(十七):团队如何管理UI Prompt——减少产品、设计与开发之间的信息损耗
前端·prompt
资讯综合1 小时前
2026全国云渲染网站排名 不同需求用户适配榜单
开发语言·前端·javascript
letisgo51 小时前
JAVA 高级进阶10篇《消息队列实战:RocketMQ/Kafka选型与“不丢不重有序“三连解》
java·面试·kafka·消息队列·rocketmq
PHP实战开发录1 小时前
PHP接口超时后为什么任务还在跑
开发语言·前端·php·开发