深拷贝与浅拷贝

文章目录


前言

怎么区分深拷贝和浅拷贝呢?

let a = [0,1,2,3,4]
let b = a;
console.log(b);  //[0,1,2,3,4]
a[0] =1;
console.log(b);  //[1,1, 2, 3, 4] 

 根据上面的例子,b复制了a,当我们修改a的时候,b的值也跟着发生了变化,这就是浅拷贝。如果我们修改a后,b没有变化,那么它就是深拷贝了。


一、基本数据与引用数据类型

为什么我们修改了a,b也会跟着变化呢?
那就要涉及到基本数据类型与引用数据类型的概念了。
基本数据类型:numberstringbooleannullunderfinedsymbol 以及es10新增的BigInt
引用数据类型:objectarrayfunction。 

  • 基本数据类型名和值是存放在栈中的。
    例如:let a = 1; b = a;

 a= 1时会在栈内存中开辟内存存放对应名值。

  b = a时栈内存会新开辟一个内存,存放b的值,两个变量拥有各自的空间互补干扰,所以我们修改b时a并不会受到影响。虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。

               

  •  引用数据类型--名和地址指针在栈内存中,值存在于堆内存中。

当obj1 = obj 进行拷贝,实际是在栈中开辟内存来存放obj1,对应值同为obj所对应的地址指针。

即为obj1与obj同指向堆内存中的同一个值。 

 当我们对obj[0] = 1进行数组修改时,由于obj与obj1指向的是同一个地址,所以自然obj1也受了影响,这就是所谓的浅拷贝了。

 

二、如何实现深拷贝?

1.通过JSON.stringify()和JSON.parse()

 由上图可以看出,obj通过JSON.parse(JSON.stringify())给obj1赋值后,改变obj中属性值,obj1并没有随之变化,实现了深拷贝。

但是,这个方法也是有缺陷的:

let a={ 
        name:'小小',
        age:20,
        num:undefined,
        no:Symbol(1),
        info:function(){return {address:'河北',iphone:'1234567'}}
}
let b = JSON.parse(JSON.stringify(a));
b //{name: "小小", age: 20}
a //{name: "笑笑", age: 20, num: undefined, no: Symbol(1), info: ƒ}

如上可以看出, JSON.parse(JSON.stringify())不能复制function,undefined和symbol,同样也无法解决循环引用的对象,会造成数据的丢失。

2.通过递归方式遍历底层进行深拷贝 

let obj={ 
        name:'小小',
        age:20,
        num:undefined,
        no:Symbol(1),
        new:{name:'title',id:[2,[3,4]]},
        info:function(){return {address:'河北',iphone:'1234567'}}
}
const clone = (obj)=>{
    let data= typeof obj === 'object' ? {}:[];
    if(obj && typeof obj ==='object'){
        for(let key in obj){
            if(obj[key] && typeof obj[key]==='object'){
                data[key] = clone(obj[key])
            }else{
                data[key] = obj[key]
            }
        }
    }
    return data;
}
let obj2 = clone(obj);
obj.new.name='value';
obj.new.id[1][0]=10;
console.log(obj2);
console.log(obj);

3. 通过jq的extend方法进行深拷贝

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

object1  objectN可选。 Object类型 第一个以及第N个被合并的对象。 

let a={ 
        name:'小小',
        age:20,
        num:undefined,
        no:Symbol(1),
        new:{name:'title',id:[2,[3,4]]},
        info:function(){return {address:'河北',iphone:'1234567'}}
}
b=$.extend(true,[],a);
a.name="笑笑";
a.new.name="value";
a.new.id[1][0] = 10;
console.log(a,b);

 

 4.只能深度拷贝对象的第一层

  • Object.assign() 对象的合并 
  • Array.slice()方法
  • Array.concat()方法
  • es6解构赋值

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝。 

关于JSON.parse(JSON.stringify())深拷贝的补充。 

  •  obj里面有new Date(),深拷贝后,时间会变成字符串的形式。而不是时间对象;
  • obj里有RegExp、Error对象,则序列化的结果会变成空对象{};
const a ={
     name:'a',
     date:new RegExp('\\w+'),
};
const b =JSON.parse(JSON.stringify(a));
 a.name ='test'
 console.log( a, b)
  •  obj里有NaN、Infinity和-Infinity,则序列化的结果会变成nul。
const a ={
    name:'a',
   date:NaN,
};
const b =JSON.parse(JSON.stringify(a));
a.name ='test'
console.log(a, b)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深拷贝浅拷贝是在对象拷贝过程中所使用的两种不同的方法。深拷贝会创建一个新的对象,并递归地复制所有嵌套的对象,包括对象的所有属性。这意味着,新对象与原始对象是完全独立的,对新对象的修改不会影响原始对象。 浅拷贝则是创建一个新的对象,但是只复制原始对象的引用,而不复制嵌套对象本身。这意味着,新对象与原始对象共享相同的嵌套对象,对新对象或原始对象的嵌套对象进行修改都会互相影响。 在Python中,可以使用copy模块中的copy()函数来进行浅拷贝,使用deepcopy()函数来进行深拷贝。例如,对于列表a,可以使用copy.copy(a)进行浅拷贝,使用copy.deepcopy(a)进行深拷贝。 总结起来,深拷贝会创建一个新的对象,并递归地复制所有嵌套对象,而浅拷贝只复制原始对象的引用。因此,深拷贝会产生独立的对象,而浅拷贝则会共享嵌套对象。这就是深拷贝浅拷贝的区别。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python的深拷贝浅拷贝](https://download.csdn.net/download/weixin_38644097/13749157)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [让你彻底理解浅拷贝深拷贝的区别](https://blog.csdn.net/weixin_43878906/article/details/108358240)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [浅拷贝深拷贝的区别](https://blog.csdn.net/m0_73770538/article/details/126898545)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值