一文解读深浅拷贝的理解和几种使用方法

深拷贝和浅拷贝是面试中经常被问到了,理解其原理和深浅拷贝差异以及多种深浅拷贝方法才能熟练在实际项目中使用做到游刃有余。本文将从作用原理到具体代码实现和多种使用方法进行展开解读。

深浅拷贝的理解

浅拷贝

浅拷贝从字面意义上就是浅层的拷贝对象,不涉及到深层次的拷贝,也就是说只复制对象表层数据,只是为原来的对象创建新的内存,但是嵌套的引用类型(如:数组、子对象)仍然需要与原对象共享内存,修改副本的嵌套字段会同步影响原对象,进而产生污染。

其核心就是,由于JS的数据类型的存储机制,基本类型(字符串、数字等)直接存在 内存中,复杂类型(对象、数组等)在栈中只存堆内存的地址引用,而堆内存才存实际的数据。浅拷贝时,只是复制栈内存而不对堆内存进行复制。 如图:

极简代码理解就是:

js 复制代码
// 原始对象
const userInfo = { 
    name: "张三", // 基本类型(直接存在栈内存里) 
    address: { city: "北京" } // 复杂数据类型(地址引用在栈,实际数据在堆) 
    };
// 浅拷贝:创建新对象
const formData = { ...userInfo }; 
// 1. 对比新对象本身的地址
console.log(userInfo === formData); // false,说明地址不同,是新的内存
// 2. 对比嵌套address的地址
console.log(userInfo.address === formData.address); // true,相同,说明内存共享,指向的是同一个地址
// 3. 修改嵌套字段,验证污染 
formData.address.city = "上海"; 
console.log(userInfo.address.city); // 输出"上海",说明原对象被污染了

深拷贝

理解了浅拷贝,深拷贝就是完全复制原始对象及所有的嵌套数据 ,会为原对象和所有嵌套的引用类型(如数组、子对象)创建独立的内存空间,副本与原对象彻底隔离,修改副本不会影响到原对象

深浅拷贝的方法

浅拷贝的5种常用方法

1. 对象展开运算符{...obj},最简洁的实现方式,适用于普通对象

js 复制代码
const shallowCopy = { ...userInfo };

2.数组展开运算符,数组专属浅拷贝

js 复制代码
const shallowCopy = { ...originArr };

3.Object.assign(target,source),可以合并多个对象,仅浅拷贝源对象表层

js 复制代码
const shallowCopy = Object.assign({},userInfo1,userInfo2,userInfo3,....);

4.数组slice(),数组截取(不传参时等价于浅拷贝)

js 复制代码
const shallowCopy = originalArr.slice();

5.数组concat(),拼接空数组实现浅拷贝

js 复制代码
const shallowArr = originalArr.concat([]);

深拷贝的4种常用方法

1.JSON.parse(JSON.stringify(obj)),最常用(局限性:不支持函数、Symbol、Date、RegExp)

js 复制代码
const deepCopy = JSON.parse(JSON.stringify(userInfo));

2.递归遍历拷贝, 自定义实现(灵活处理所有类型,需手写逻辑),面试手写题常考

js 复制代码
function deepClone(obj){
    // 类型判断 
    if(obj isntanceof Date) return new Date(obj);
    if(obj instanceof RegExp) return new RegExp(obj);
    if(obj instanceof Error) return new Error(obj.message);
    if(obj instanceof Function) return function(...args){
        return obj.call(this,...args);
    };
    if( obj === null || typeof obj !== 'object') return obj;
    
    const newObj = Array.isArray(obj) ? [] : {};
    
    for(let key in obj){
        if(Object.hasOwn(obj,key)){
            if(typeof obj[key] === "object"){
                newObj[key] = deepClone(obj[key]); // 递归拷贝嵌套层
            }
            else{
                newObj[key] = obj[key]
            }
        }
         
    }
    return newObj;
}

3.第三方库, 稳定可靠(开发首选)

  • Lodash中的 _.cloneDeep(obj)(支持所有类型,处理循环引用)
  • jQuery中的 $.extend(true,{},obj)(第一个参数为true表示深拷贝)

4.structuredClone(), 浏览器原生API,支持循环引用、Date/RegExp,但不支持函数

相关推荐
passerby606110 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了17 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅20 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅42 分钟前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅1 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊1 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc