核心在于浅拷贝仅断开第一层引用,深层嵌套仍共享内存;深拷贝则彻底隔离所有层级。实战中,含引用类型且后续可能修改时须判断拷贝方式:仅读取或改基本类型字段→浅拷贝足够;需修改子属性、push/splice或传第三方函数→必须深拷贝。推荐用structuredclone(现代环境)或lodash.clonedeep(兼容复杂结构),并务必动手验证隔离效果。

核心在于:浅拷贝只切断第一层引用,深层嵌套对象仍共用内存;深拷贝则彻底隔离所有层级。实战中,只要数据含对象、数组等引用类型,且后续可能被修改,就必须判断是否需要深拷贝。
一眼识别该用哪种拷贝
看变量结构和后续操作:
- 仅读取或只改基本类型字段(如 name、id)→ 浅拷贝足够
- 要 push/splice/赋新对象给子属性(如 user.profile.address.city = '上海')→ 必须深拷贝
- 传给第三方函数(如表单校验、图表库 setData)→ 默认按深拷贝处理,除非文档明确说“只读”
常见浅拷贝陷阱与绕过方式
这些操作看着像复制,实际仍是共享引用:
- Object.assign({}, obj) 和 {...obj}:只拷贝第一层,obj.items[0].done = true 会同步影响原对象
- Array.from(arr) 或 arr.slice():对一维数组安全,但 arr[0].price = 99 会污染原数组
- JSON.parse(JSON.stringify(obj)):能深拷贝,但丢函数、undefined、Date、RegExp、循环引用
生产环境推荐的深拷贝方案
不拼手写递归,优先选稳定可靠的方式:
- 简单场景(无函数/日期/特殊值):用 structuredClone(obj)(现代浏览器 & Node.js 17+ 原生支持,性能好、语义清晰)
- 兼容老环境或复杂结构:引入 lodash.cloneDeep(自动处理 Map/Set/Date/正则/循环引用)
- 状态管理(如 React/Vue):用不可变更新库(immer),写法自然:produce(state, draft => { draft.user.name = '新名' })
关键检查点:改完立刻验证是否真隔离
别只信文档,动手验证最可靠:
- 改拷贝后对象的任意嵌套属性(如 copy.data.list[0].id)
- 立刻检查原对象对应路径:console.log(original.data.list[0].id)
- 结果不同 → 深拷贝成功;相同 → 还在共享引用,回退换方法











