JS拷贝规范核心是建立“何时用、用什么、怎么验”判断链:必须深拷贝用户输入、远程payload等;允许浅拷贝纯UI props;禁止拷贝DOM/函数等;现代环境用structuredClone(),旧环境统一lodash.cloneDeep;浅拷贝统一用展开运算符;每次拷贝后须断言验证隔离性,并强制注释意图。

制定 JS 浅拷贝与深拷贝的代码规范,核心不是罗列方法,而是建立“何时用、用什么、怎么验”的判断链。规范要能防线上事故(比如配置被意外污染)、保团队协作一致、兼顾可维护性,而不是堆砌语法糖。
明确区分场景:哪些必须深拷贝,哪些允许浅拷贝
不加判断地统一用深拷贝,会带来性能浪费和隐蔽风险(如循环引用崩溃);全用浅拷贝又极易引发数据污染。规范应按数据用途分级:
-
必须深拷贝:用户输入/表单数据、远程响应原始 payload、全局配置对象(如
theme、options)、状态快照(如 undo/redo)、测试 fixture 数据 -
允许浅拷贝:纯 UI 展示用的扁平 props(无嵌套对象)、临时计算中间值(生命周期短且不透出)、只读数组切片(如
items.slice(0, 10)) - 禁止拷贝:DOM 元素、函数、正则、Date 实例(除非明确需要副本)、已封装的类实例(应走 clone 方法而非通用拷贝)
方法选型强制约定:按环境与需求锁定实现
避免团队内五花八门写法(有人用 JSON.parse(JSON.stringify()),有人手写递归,有人乱用 Object.assign),规范需硬性约束:
-
现代浏览器环境(Chrome 98+ / Firefox 94+ / Safari 15.4+):优先使用
structuredClone(),它是原生、安全、完整支持 Map/Set/Date/RegExp/ArrayBuffer/循环引用的唯一标准方案 -
需兼容旧版浏览器:统一引入
lodash.cloneDeep,禁用自行手写深拷贝(易漏循环引用、Symbol、不可枚举属性等) -
浅拷贝统一写法:对象用
{...obj},数组用[...arr];禁用Object.assign({}, obj)(语义弱、易误用于多源合并)和arr.slice()(数组专属,不具一致性)
验证与防御:每次拷贝后必须做的两件事
规范不能只写“怎么做”,更要写“怎么确认做对了”。所有拷贝操作后,必须显式验证嵌套修改是否隔离:
-
必加断言测试:在关键路径(如配置处理、表单提交前)插入校验逻辑:
const copy = structuredClone(original);<br>copy.nested.value = 'changed';<br>console.assert(original.nested.value !== 'changed', '深拷贝失效:原始数据被污染');
-
静态检查兜底:在 ESLint 中启用
no-restricted-syntax规则,禁止未包裹验证的JSON.parse(JSON.stringify())出现在业务代码中(仅限 mock 或非关键路径)
注释与文档:让意图可读,不靠人脑记忆
拷贝不是技术炫技,是为明确数据所有权。规范要求所有拷贝操作旁必须带注释,说明“为什么需要这份副本”:
- ✅ 合规注释:
// 深拷贝:防止用户编辑影响原始模板配置 - ❌ 违规注释:
// 拷贝一下或// 防止引用问题(模糊、无上下文) - 对外暴露的 API 接口文档中,必须标注参数/返回值是否为深拷贝结果(例如:“返回配置对象的深拷贝副本,修改不影响内部状态”)











