浅拷贝只断开第一层引用,深拷贝递归断开所有层级引用;根本原因在于javascript中基本类型存栈、赋值即复制值,引用类型变量存栈中地址、实际数据在堆,赋值仅复制地址,故改嵌套对象会影响原对象。

直接说核心:浅拷贝只断开第一层引用,深拷贝递归断开所有层级的引用。关键不在背方法,而在讲清“为什么改嵌套对象会影响原对象”——因为变量存的是地址,不是数据本身。
先画内存图,把栈和堆讲清楚
面试官一听你主动提内存模型,立刻知道你不是死记硬背。一句话点明:
- 基本类型(string/number/boolean等)存在栈里,赋值=复制值,互不影响
- 引用类型(object/array等)实际数据在堆里,变量在栈里只存一个地址,赋值=复制地址,指向同一块堆内存
- 浅拷贝就是新建一个对象(新地址),但内部引用类型的属性,还是把旧地址抄过去
- 深拷贝是每层都新开堆空间,彻底不共用任何地址
被问到具体方法时,别罗列,带出边界
比如说到 Object.assign() 或展开运算符:
- 它们是浅拷贝,能解决一层平铺对象的隔离,比如表单初始值备份
- 但遇到
{user: {profile: {name: 'a'}}},改copy.user.profile.name会同步影响原对象 - 数组同理:
[1, {x: 2}]浅拷后,改copy[1].x原数组也变
聊深拷贝,避开 JSON 方法的坑是加分项
很多人张口就说 JSON.parse(JSON.stringify(obj)),但面试官就等你踩这个雷:
- 函数、undefined、Symbol、BigInt 会丢失
- Date、RegExp、Map、Set 会被转成空对象或字符串
- 循环引用直接报错(
Converting circular structure to JSON) - 真正安全的方案:Chrome 98+ 用
structuredClone(),兼容性差时手写递归 + WeakMap 处理循环引用
最后补一句落地意识,拉高回答层次
不用说“我项目里都用lodash”,而是点出场景逻辑:
- Vue 的
watch深度监听、React 的不可变更新(reducer 中不能改 state 原对象),底层都依赖对拷贝行为的准确判断 - 状态管理中一个错误的浅拷贝,可能让组件重渲染失效或引发隐蔽的响应式丢失
- 所以选哪种拷贝,不是看“能不能”,而是看“该不该”——性能、数据结构复杂度、是否含特殊类型,都要权衡











