知

模块五 · AI 协作与表达

第 13 / 14 节19 分钟阅读型

AI 协作与代码评审:语言与浏览器层怎么审

语言、网络、浏览器这些"地基"是 AI 最容易糊弄的地方:能跑、有类型、看起来没问题,但兼容性、竞态和安全处处是洞。这一节给出地基层的评审清单。

读完这一节,你能做到

  1. 说清 AI 在前端基础层最常犯的四类错。
  2. 用「目标 / 现状 / 约束 / 验收」写出带环境约束的上下文。
  3. 按「类型 → 纯函数 → 副作用 → 测试」拆解一个前端任务。
  4. 用五个检查点审出兼容性、竞态与安全上的坑。
  5. 用 tsc、单测与浏览器面板证明改动没有变坏。

一、地基层的特殊风险

框架层出错通常立刻报错,地基层出错往往静默:== 的隐式转换、闭包捕获的旧值、innerHTML 拼出来的 XSS、浏览器不支持的 API、被缓存卡住的资源。AI 生成的代码在 Chrome 最新版上跑通了,不代表它在你的用户环境里成立。

它很擅长它经常错
语法、API 用法、常见算法兼容性(用了没 polyfill 的新 API)
类型标注的写法类型是否真的生效(any、as、断言兜底)
正则、格式化、小工具异步竞态与错误吞掉
文档与示例安全(innerHTML、eval、拼接 SQL)

判断原则:地基层的"对"要加上环境限定。 不说清浏览器范围、Node 版本、TS 严格度,它给你的就是"在它想象的环境里对"。

二、上下文:把环境写进去

地基类任务的上下文,多一个维度——运行环境:

  1. 目标:这段代码要在哪跑、解决什么问题、验收看什么。
  2. 现状:浏览器支持范围(是否要兼容旧版)、Node 版本、构建工具、TS 配置(strict 是否开)、现有工具函数在哪。
  3. 约束:不新增依赖、必须走现有 request 封装、不许用 any、必须能在不支持 ?: 的环境里编译。
  4. 验收:行为级——输入什么输出什么、错误怎么显示、性能上限是多少。

反例与正例的差别,就在这里:

反例:帮我写一个深拷贝函数。
正例:目标:对象深拷贝,用于把接口返回的数据与表单状态隔离。
      现状: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、手机号)打进日志?

五、验证:三道闸

  1. 静态闸:tsc --noEmit(确认 strict 开着)+ ESLint。能拦掉大部分类型洞与不安全写法。
  2. 行为闸:Vitest 覆盖纯函数边界(空值、超长、循环引用、非法字符),再手测真实浏览器交互。
  3. 环境闸:这次改动在目标浏览器里跑过吗?Network 面板看缓存策略生效了吗?Performance 面板看长任务吗?

第三闸是地基层特有的:它在你的 Chrome 上没问题,不等于它在用户手机上没问题。

六、算例:一个工具函数的两种做法

任务:写一个带并发上限的批量请求工具,要求能拿到成功与失败两类结果。时长示意。

做法 A:一次要完

项耗时
写提示词、等生成2 分钟
review 90 行15 分钟
发现用 Promise.all,一个失败全丢返工 20 分钟
补测试时发现并发上限是假的返工 15 分钟
合计52 分钟

做法 B:拆两轮

轮次交给 AI 的自己做的耗时
① 纯函数限流器骨架定签名与失败收集结构10 分钟
② 副作用请求包装接 AbortController、错误归类10 分钟
③ 测试用例骨架补并发数与失败路径断言12 分钟
合计32 分钟
净收益 = 生成节省的时间 − (审查 + 返工 + 事故成本)

地基层的返工还有个特点:它往往不是改一行,而是推翻整个结构。Promise.all 换成"部分成功",函数签名要跟着变,调用方也要改。

七、常见坑

  1. 只看 Chrome 最新版。 兼容性问题在开发机上永远复现不了。
  2. 把类型当成装饰。 一堆 any 的代码,tsc 通过但等于没检查。
  3. 异步错误被吞。 空 catch {} 是最常见的 AI 产物之一,出问题时线上没有任何线索。
  4. 用 innerHTML 图省事。 用户输入直接拼进 DOM,XSS 一步到位。
  5. 让它写正则不验证边界。 特殊字符、超长输入、回溯爆炸都要单独测。
  6. 把真实接口地址、token 贴进提示词。 这类信息不该出现在公网模型里。

八、面试怎么讲

"你怎么用 AI 写前端"这道题,在基础层岗位上考得更细——因为基础层的错误更难发现。

怎么用:先定类型、再写纯函数、最后包副作用,每轮只让它产出一屏 diff
怎么验:tsc strict + 单测覆盖边界 + 目标浏览器实跑
踩过什么坑:它默认用 structuredClone,Safari 14 直接报错;后来把兼容范围写进上下文
换来什么:工具函数从 52 分钟降到 32 分钟,返工集中在"部分失败"这类结构问题上

一个加分说法:"我审 AI 代码时最看异步和安全两块,因为这两类错误不会在 happy path 上暴露。"

九、动手任务:自写 → AI 写 → 对比 → 取舍

四步不跳:① 自己写(限时,关掉补全)→ ② 让 AI 写同一题 → ③ 逐条比对 → ④ 说出保留谁的写法。

① 自己写

  1. 写一个 mapLimit(items, limit, fn):并发上限、失败可继续、返回成功与失败两类结果。
  2. 写一个 escapeHtml(str),并说明它为什么比 textContent 差。

② 让 AI 写同一题

把第 1 题交给 AI,补一句 TS strict,不引依赖,失败不能中断其他任务,必须能拿到失败列表。

③ 对比要盯的点

检查面我的版本AI 版本差异说明
并发是否真限流
失败是否可继续
类型是否生效
边界(空数组 / limit > 长度)

④ 说取舍

  1. 它用 Promise.all 还是自己维护在跑的队列?
  2. limit 大于数组长度、数组为空时,它会不会卡死?
  3. 它的实现能在 Safari 14 上跑吗?

十、自测

  1. 地基层的错误为什么比框架层更难发现?
  2. 上下文里"环境"这一维具体要写什么?
  3. 为什么推荐"纯函数 → 副作用"的顺序?
  4. 五个检查点分别是什么?哪一类错误不会在 happy path 上暴露?
  5. 三道闸里"环境闸"指什么?
  6. Promise.all 与 allSettled 的差别,在什么场景下必须用后者?

参考答案要点:不报错、只在特定环境或数据下暴露;浏览器范围、Node 版本、TS 严格度、构建工具;纯函数可测、副作用层薄;异步竞态、类型生效、兼容性、安全、可观测性,异步与安全;在目标浏览器与真实网络策略下实跑;一个 reject 即整体失败,需要部分成功时用后者。

配套题目

★ 越多越该先背;点题目可看完整答案与深入版。

提示:读完可以顺手做几道对应题目,检验是否真的理解