浅拷贝只复制第一层属性,嵌套引用类型仍共享内存;深拷贝递归复制所有层级,为每个嵌套对象开辟新内存空间。本质区别在于是否切断引用类型的内存共享关系,核心是一层复制 vs 全层独立。
浅拷贝与深拷贝的本质区别,在于是否切断引用类型的内存共享关系:浅拷贝只复制对象第一层属性,对嵌套的引用类型仍保留原地址;深拷贝则递归复制所有层级,为每个嵌套对象开辟全新内存空间。
JavaScript 中基本类型(如 number、string)赋值即拷贝值,互不影响;而引用类型(object、array 等)在内存中分两部分存储:栈中存地址,堆中存实际数据。拷贝行为的关键就落在这个“地址”是否被复用上:
这些方式都只处理第一层,适合结构扁平、无深层嵌套的场景:
{...obj} 或 [...arr] ——简洁常用,但对 undefined、function、Date、RegExp 等特殊对象会丢失或出错Object.assign({}, obj) ——兼容性好,但同样不处理嵌套对象,且忽略不可枚举属性和原型链arr.slice()、arr.concat()、[].concat(arr) ——仅适用于数组,且对数组内含对象仍为浅拷贝没有银弹方案,需按需求选型:
立即学习“Java免费学习笔记(深入)”;
JSON.parse(JSON.stringify(obj)) ——最简,但会丢弃 function、undefined、Symbol、Date、RegExp,且无法处理循环引用,仅适合纯数据对象(如 API 响应体)structuredClone(obj)(Chrome 98+、Node.js 17.0+ 支持)——原生、安全、支持多数内置类型(包括 Date、Map、Set、ArrayBuffer),但暂不支持函数和自定义类实例_.cloneDeep() 功能全面,能处理函数、循环引用、特殊对象,但引入额外体积Array / Date / Map 等)和性能问题什么时候该用哪种?关键看“改了副本,原数据能不能动”:
Object.assign(defaults, userConfig))Date、Map 等对象时,JSON 方法会失效,应优先考虑 structuredClone 或库方案