掌握浅拷贝与深拷贝的关键在于理解“操作的是值还是地址”:值类型赋值复制数据本身,引用类型赋值复制地址;浅拷贝仅第一层独立,深拷贝彻底隔离嵌套;用修改嵌套属性是否影响原对象可快速验证。

掌握浅拷贝与深拷贝,关键不是背方法,而是理解“你操作的是值,还是地址”这个底层逻辑。只要这个点吃透,所有方案和坑都能自然推出来。
先死磕内存模型:栈 vs 堆 + 值类型 vs 引用类型
这是所有拷贝问题的起点,跳过这步,后面全是空中楼阁。
- 值类型(string/number/boolean/null/undefined/Symbol/BigInt):变量里直接存数据本身。赋值 = 真复制一份新值,互不影响
- 引用类型(Object/Array/Date/RegExp/Function/Map/Set):变量里存的是内存地址。赋值 = 复制地址,两个变量指向同一块堆内存
- 打个比方:赋值一个对象,就像把同一把钥匙给了两个人;浅拷贝是再配一把钥匙,但开的还是同一个房间;深拷贝才是重新盖一栋一模一样的房子
用“改嵌套属性是否影响原对象”一句话判断深浅
别记定义,动手试。写一行代码就能验证:
- const a = { x: 1, y: { z: 2 } }; const b = /* 你的拷贝方式 */; b.y.z = 99;
- 如果 console.log(a.y.z) 输出 99 → 是浅拷贝
- 如果输出 2 → 是深拷贝(或至少对这一层生效了)
- 这个测试比背十个方法都管用,面试和 debug 时随时可用
主流方法要分三类记,不按语法糖归类
按能力边界记,避免误用:
- 纯浅拷贝工具:展开运算符 {...obj}、Object.assign()、Array.slice()、Array.concat()、Array.from() —— 它们只保第一层独立,嵌套全共享
- 伪深拷贝(有硬伤):JSON.parse(JSON.stringify(obj)) —— 简单场景快,但会丢函数、undefined、Symbol、Date、RegExp,且无法处理循环引用
- 真深拷贝方案:手写递归(带 WeakMap 解循环引用)或使用 lodash 的 _.cloneDeep() —— 能覆盖所有类型和边界情况
实战避坑口诀:看结构选方案
不用纠结“哪个最好”,只问“当前数据长什么样”:
- 数据是纯扁平对象或数组(无嵌套、无特殊类型)→ 用展开运算符,够用又快
- 数据含简单嵌套,且确认不含函数/日期/undefined/Symbol/循环引用 → JSON 方案可应急
- 数据来自接口、配置项、表单状态等不确定结构 → 直接上 _.cloneDeep() 或封装好的递归深拷贝函数
- 在 React/Vue 中更新 state 或 props → 优先用不可变更新模式(如 immer),而不是手动拷贝











