直接上手实战项目比背概念有效十倍:以典型嵌套数据结构为靶子,设计表单编辑撤回、组件局部更新、配置合并覆盖、状态缓存判断四类场景,横向对比赋值、展开运算符、object.assign、json方案、structuredclone及手写递归六种拷贝方式行为,并封装可切换策略的拷贝工具函数。

直接上手做一个能暴露问题、验证方案、贴合真实业务的实战项目,比背概念有效十倍。核心思路是:用一个典型嵌套数据结构作为“靶子”,设计几类高频修改场景,再逐个用不同拷贝方式处理,观察行为差异。
一、构建一个有代表性的测试数据源
定义一个含多层嵌套、混合类型、常见内置对象的配置对象:
- 包含普通属性(string/number/boolean)
- 含嵌套对象(info: { age, hobbies })
- 含数组(tags: ['js', 'react'])
- 含 Date、RegExp、Map 等非 JSON 友好类型
- 手动构造一个循环引用(self: null → 指回自身)
这个结构能一次性触发浅拷贝失效、JSON 方案报错、递归方案漏处理等典型问题。
二、设计四类真实修改场景
每种场景对应一类线上高频故障:
-
表单编辑后撤回:修改副本的
name和info.age,点击“还原”时需恢复原始值 —— 浅拷贝会让info.age还原失败 -
组件局部更新:子组件只改
tags数组内容,父组件的原始tags不应被 push 或 splice 影响 -
配置合并覆盖:用户传入
{ info: { city: 'Beijing' } },需与默认配置深度合并,不能让info.hobbies丢失 -
状态缓存判断:用
useMemo缓存计算结果,依赖项含对象,若拷贝不彻底会导致重复执行
三、横向对比六种拷贝方式的行为
对同一份原始数据,分别用以下方式生成副本,然后运行上述四类场景,记录是否出错:
-
赋值(
const copy = original):所有修改都影响原对象,作为对照组 -
展开运算符(
{...original}/[...arr]):第一层安全,嵌套对象/数组仍共享 - Object.assign({}, original):同展开,且忽略原型链和不可枚举属性
-
JSON.parse(JSON.stringify()):能断开嵌套,但丢
Date、RegExp、undefined、function,遇循环引用直接崩溃 -
structuredClone():现代浏览器可用,支持
Map/Set/Date/RegExp,但不支持function和循环引用(Chrome 98+、Safari 16.4+) - 手写递归 + WeakMap 版深拷贝:完整支持所有类型,能处理循环引用,但性能略低
四、封装一个可切换的拷贝工具函数
写一个带策略参数的工具函数,方便在开发中快速切换验证:
- 接受
data和strategy: 'shallow' | 'json' | 'structured' | 'deep' - 内部按策略调用对应实现,统一处理错误(如 JSON 失败时 fallback 到递归)
- 加日志输出当前使用方案、耗时、是否检测到循环引用等信息
这样你在调试表单或状态管理时,只需改一个参数,就能立刻看到不同拷贝方式对整个流程的影响。











