一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

JavaScript 中浅拷贝与深拷贝的本质区别与应用场景

时间:2026-07-01 11:19:51 编辑:袖梨 来源:一聚教程网

浅拷贝只复制第一层属性,嵌套引用类型仍共享内存;深拷贝递归复制所有层级,为每个嵌套对象开辟新内存空间。本质区别在于是否切断引用类型的内存共享关系,核心是一层复制 vs 全层独立。

浅拷贝与深拷贝的本质区别,在于是否切断引用类型的内存共享关系:浅拷贝只复制对象第一层属性,对嵌套的引用类型仍保留原地址;深拷贝则递归复制所有层级,为每个嵌套对象开辟全新内存空间。

核心差异:一层 vs 全层

JavaScript 中基本类型(如 number、string)赋值即拷贝值,互不影响;而引用类型(object、array 等)在内存中分两部分存储:栈中存地址,堆中存实际数据。拷贝行为的关键就落在这个“地址”是否被复用上:

  • 浅拷贝:新对象的顶层属性值如果是基本类型,就复制值;如果是引用类型(比如一个子对象或数组),就复制那个地址——新旧对象仍指向堆中同一块数据
  • 深拷贝:无论嵌套多深,遇到引用类型就新建堆内存、逐层复制内容,最终两个对象完全独立,修改互不干扰

常见浅拷贝方法及局限

这些方式都只处理第一层,适合结构扁平、无深层嵌套的场景:

  • 展开运算符{...obj}[...arr] ——简洁常用,但对 undefinedfunctionDateRegExp 等特殊对象会丢失或出错
  • Object.assign()Object.assign({}, obj) ——兼容性好,但同样不处理嵌套对象,且忽略不可枚举属性和原型链
  • 数组方法arr.slice()arr.concat()[].concat(arr) ——仅适用于数组,且对数组内含对象仍为浅拷贝

深拷贝的实现方式与取舍

没有银弹方案,需按需求选型:

立即学习“Java免费学习笔记(深入)”;

  • JSON 方法JSON.parse(JSON.stringify(obj)) ——最简,但会丢弃 functionundefinedSymbolDateRegExp,且无法处理循环引用,仅适合纯数据对象(如 API 响应体)
  • 结构化克隆(现代推荐)structuredClone(obj)(Chrome 98+、Node.js 17.0+ 支持)——原生、安全、支持多数内置类型(包括 DateMapSetArrayBuffer),但暂不支持函数和自定义类实例
  • 第三方库:Lodash 的 _.cloneDeep() 功能全面,能处理函数、循环引用、特殊对象,但引入额外体积
  • 手写递归:可控性强,可定制过滤逻辑(如跳过某些字段),但需谨慎处理循环引用、类型识别(Array / Date / Map 等)和性能问题

典型应用场景对比

什么时候该用哪种?关键看“改了副本,原数据能不能动”:

  • 用浅拷贝:表单初始值快照(仅顶层字段)、UI 组件 props 透传(避免直接修改父级状态)、临时合并配置项(如 Object.assign(defaults, userConfig)
  • 必须用深拷贝:编辑表单草稿时保存原始数据用于“取消”还原、Vuex/Pinia 中 state 初始化、测试中构造隔离数据、后端返回的数据需要本地持久化并频繁修改
  • 注意陷阱:Vue/React 中直接修改 props 或响应式对象的嵌套属性,即使用了浅拷贝也可能触发视图更新异常;涉及 DateMap 等对象时,JSON 方法会失效,应优先考虑 structuredClone 或库方案

热门栏目