模块五 · AI 协作与表达
AI 协作与代码评审:语言与浏览器层怎么审
语言、网络、浏览器这些"地基"是 AI 最容易糊弄的地方:能跑、有类型、看起来没问题,但兼容性、竞态和安全处处是洞。这一节给出地基层的评审清单。
读完这一节,你能做到
- 说清 AI 在前端基础层最常犯的四类错。
- 用「目标 / 现状 / 约束 / 验收」写出带环境约束的上下文。
- 按「类型 → 纯函数 → 副作用 → 测试」拆解一个前端任务。
- 用五个检查点审出兼容性、竞态与安全上的坑。
- 用
tsc、单测与浏览器面板证明改动没有变坏。
一、地基层的特殊风险
框架层出错通常立刻报错,地基层出错往往静默:== 的隐式转换、闭包捕获的旧值、innerHTML 拼出来的 XSS、浏览器不支持的 API、被缓存卡住的资源。AI 生成的代码在 Chrome 最新版上跑通了,不代表它在你的用户环境里成立。
| 它很擅长 | 它经常错 |
|---|---|
| 语法、API 用法、常见算法 | 兼容性(用了没 polyfill 的新 API) |
| 类型标注的写法 | 类型是否真的生效(any、as、断言兜底) |
| 正则、格式化、小工具 | 异步竞态与错误吞掉 |
| 文档与示例 | 安全(innerHTML、eval、拼接 SQL) |
判断原则:地基层的"对"要加上环境限定。 不说清浏览器范围、Node 版本、TS 严格度,它给你的就是"在它想象的环境里对"。
二、上下文:把环境写进去
地基类任务的上下文,多一个维度——运行环境:
- 目标:这段代码要在哪跑、解决什么问题、验收看什么。
- 现状:浏览器支持范围(是否要兼容旧版)、Node 版本、构建工具、TS 配置(
strict是否开)、现有工具函数在哪。 - 约束:不新增依赖、必须走现有
request封装、不许用any、必须能在不支持?:的环境里编译。 - 验收:行为级——输入什么输出什么、错误怎么显示、性能上限是多少。
反例与正例的差别,就在这里:
反例:帮我写一个深拷贝函数。
正例:目标:对象深拷贝,用于把接口返回的数据与表单状态隔离。
现状:TS strict,目标浏览器含 Safari 14,项目已有 utils/clone.ts。
约束:不引入 lodash;要处理 Date、Map、Set、循环引用;不许用 structuredClone
(Safari 14 不支持)。
验收:循环引用不爆栈、函数与 DOM 节点按引用返回、1 万节点对象耗时 < 20ms。
同一句话,第二个能一次要出可用的东西,第一个大概率给你一个 JSON.parse(JSON.stringify()) 或者直接 structuredClone。
三、拆任务:先纯函数,后副作用
地基层的任务有个天然优势:大部分可以写成纯函数。所以顺序固定:
① 定输入输出类型 → ② 写纯函数与边界 → ③ 包一层副作用(DOM / 请求 / 存储)→ ④ 补测试
好处很直接:纯函数能单测、能复核;副作用层只剩薄薄一层,审起来快。反过来,如果一上手就让 AI 写"页面 + 交互 + 请求 + 渲染",你会拿到一个 200 行、既不能测也不好改的函数。
粒度标准仍是:这次 diff 我能在 10 分钟里逐行看完。
四、五个检查点
第一点:异步与竞态
- 并发控制用
Promise.all:一个 reject 全盘皆输,该用allSettled或显式 catch。 - 取消:
AbortController传下去了吗?还是只发不管。 - 定时器与监听:清理了吗?页面切走后还在跑。
async函数里的错误:有没有被try/catch吞掉,只留一个空 catch。
第二点:类型是不是真的生效
- 出现
any、as any、@ts-ignore、!非空断言 —— 每一个都是闸门上的洞。 - 泛型没有约束,函数体里只能靠
any兜底。 unknown与any混用:前者强制收窄,后者放弃检查。
第三点:兼容性与降级
- 用了新 API(
structuredClone、Array.prototype.at、Object.hasOwn)却没提 polyfill 与目标浏览器。 - CSS 用了新特性但没有回退。
- 只测了最新版 Chrome,用户可能在旧版 Safari 上。
第四点:安全
innerHTML拼接用户输入 → XSS。该用textContent或显式转义。- 把 URL 参数、
postMessage数据当可信数据直接用。 - 正则写得太宽导致回溯爆炸(ReDoS)。
第五点:可观测性
- 错误是被吞掉,还是有日志与上报?
- 关键路径有耗时打点吗?出问题时能不能定位到哪一步慢?
- 有没有把敏感信息(token、手机号)打进日志?
五、验证:三道闸
- 静态闸:
tsc --noEmit(确认strict开着)+ ESLint。能拦掉大部分类型洞与不安全写法。 - 行为闸:Vitest 覆盖纯函数边界(空值、超长、循环引用、非法字符),再手测真实浏览器交互。
- 环境闸:这次改动在目标浏览器里跑过吗?Network 面板看缓存策略生效了吗?Performance 面板看长任务吗?
第三闸是地基层特有的:它在你的 Chrome 上没问题,不等于它在用户手机上没问题。
六、算例:一个工具函数的两种做法
任务:写一个带并发上限的批量请求工具,要求能拿到成功与失败两类结果。时长示意。
做法 A:一次要完
| 项 | 耗时 |
|---|---|
| 写提示词、等生成 | 2 分钟 |
| review 90 行 | 15 分钟 |
发现用 Promise.all,一个失败全丢 | 返工 20 分钟 |
| 补测试时发现并发上限是假的 | 返工 15 分钟 |
| 合计 | 52 分钟 |
做法 B:拆两轮
| 轮次 | 交给 AI 的 | 自己做的 | 耗时 |
|---|---|---|---|
| ① 纯函数 | 限流器骨架 | 定签名与失败收集结构 | 10 分钟 |
| ② 副作用 | 请求包装 | 接 AbortController、错误归类 | 10 分钟 |
| ③ 测试 | 用例骨架 | 补并发数与失败路径断言 | 12 分钟 |
| 合计 | 32 分钟 |
净收益 = 生成节省的时间 − (审查 + 返工 + 事故成本)
地基层的返工还有个特点:它往往不是改一行,而是推翻整个结构。Promise.all 换成"部分成功",函数签名要跟着变,调用方也要改。
七、常见坑
- 只看 Chrome 最新版。 兼容性问题在开发机上永远复现不了。
- 把类型当成装饰。 一堆
any的代码,tsc通过但等于没检查。 - 异步错误被吞。 空
catch {}是最常见的 AI 产物之一,出问题时线上没有任何线索。 - 用
innerHTML图省事。 用户输入直接拼进 DOM,XSS 一步到位。 - 让它写正则不验证边界。 特殊字符、超长输入、回溯爆炸都要单独测。
- 把真实接口地址、token 贴进提示词。 这类信息不该出现在公网模型里。
八、面试怎么讲
"你怎么用 AI 写前端"这道题,在基础层岗位上考得更细——因为基础层的错误更难发现。
怎么用:先定类型、再写纯函数、最后包副作用,每轮只让它产出一屏 diff
怎么验:tsc strict + 单测覆盖边界 + 目标浏览器实跑
踩过什么坑:它默认用 structuredClone,Safari 14 直接报错;后来把兼容范围写进上下文
换来什么:工具函数从 52 分钟降到 32 分钟,返工集中在"部分失败"这类结构问题上
一个加分说法:"我审 AI 代码时最看异步和安全两块,因为这两类错误不会在 happy path 上暴露。"
九、动手任务:自写 → AI 写 → 对比 → 取舍
四步不跳:① 自己写(限时,关掉补全)→ ② 让 AI 写同一题 → ③ 逐条比对 → ④ 说出保留谁的写法。
① 自己写
- 写一个
mapLimit(items, limit, fn):并发上限、失败可继续、返回成功与失败两类结果。 - 写一个
escapeHtml(str),并说明它为什么比textContent差。
② 让 AI 写同一题
把第 1 题交给 AI,补一句 TS strict,不引依赖,失败不能中断其他任务,必须能拿到失败列表。
③ 对比要盯的点
| 检查面 | 我的版本 | AI 版本 | 差异说明 |
|---|---|---|---|
| 并发是否真限流 | |||
| 失败是否可继续 | |||
| 类型是否生效 | |||
| 边界(空数组 / limit > 长度) |
④ 说取舍
- 它用
Promise.all还是自己维护在跑的队列? limit大于数组长度、数组为空时,它会不会卡死?- 它的实现能在 Safari 14 上跑吗?
十、自测
- 地基层的错误为什么比框架层更难发现?
- 上下文里"环境"这一维具体要写什么?
- 为什么推荐"纯函数 → 副作用"的顺序?
- 五个检查点分别是什么?哪一类错误不会在 happy path 上暴露?
- 三道闸里"环境闸"指什么?
Promise.all与allSettled的差别,在什么场景下必须用后者?
参考答案要点:不报错、只在特定环境或数据下暴露;浏览器范围、Node 版本、TS 严格度、构建工具;纯函数可测、副作用层薄;异步竞态、类型生效、兼容性、安全、可观测性,异步与安全;在目标浏览器与真实网络策略下实跑;一个 reject 即整体失败,需要部分成功时用后者。
配套题目
★ 越多越该先背;点题目可看完整答案与深入版。
- ★★★★★ AI 写的前端工具函数,你会重点审什么?
- ★★★★☆ 怎么给 AI 描述运行环境,才能避免兼容性问题?
- ★★★★☆ AI 生成的异步代码,最常见的错误是什么?
- ★★★★☆ AI 生成的代码里怎么防 XSS?
- ★★★☆☆ 类型检查能替代人工审 AI 代码吗?
- ★★★★☆ AI 时代还要不要学浏览器渲染与网络这些基础?
提示:读完可以顺手做几道对应题目,检验是否真的理解