原来深拷贝与浅拷贝是这样?

2022-12-19 0 793

原来深拷贝与浅拷贝是这样?
原来深拷贝与浅拷贝是这样?

为的是让听众更快的认知厚薄复本,在讲厚薄复本以后要导入基本上正则表达式 , 提及正则表达式 和 统计数据存储(栈和堆)这两个基本概念,假如早已认知,可间接埃唐佩县而此part。

JS正则表达式

Q:后端复试常问,JS的基本上统计数据类型有甚么样呀?

A:JS正则表达式分成基本上正则表达式和提及正则表达式,详尽进行分类如下表所示:

原来深拷贝与浅拷贝是这样?

Q:基本上正则表达式和提及正则表达式的存储形式有甚么相同?

A:

基本上正则表达式:cp和值都存储在栈缓存中,比如:var num=10;

num表达式在缓存中存储如下表所示:

原来深拷贝与浅拷贝是这样?
提及正则表达式:cp存储在栈缓存中,值存储在堆缓存中,但堆缓存中会提供更多两个提及门牌号对准堆缓存中的值,而那个门牌号是存储在栈缓存中的,比如:var arr=[1,2,3,4,5];

arr表达式在缓存中的存储如下表所示:

原来深拷贝与浅拷贝是这样?

对这两个基本概念有了初步了解之后,接下来正式开始讲厚薄复本。

甚么是浅复本和深复本

在讲两者基本概念以后我们先看两个需求:现在有两个对象A,需求是将A复本一份到B对象当中?

浅复本

当B复本了A的统计数据,且当B的改变会导致A的改变时,此时叫B浅复本了A,比如:

//浅复本 var A={ name:”martin”, data:{num:10} } var B={} var B=A; B.name=”lucy”; console.log(A.name); //lucy

A间接赋值给B后,B中name属性的改变导致了A中name属性也发生了变化。

原来深拷贝与浅拷贝是这样?

其实是因为这种赋值形式只是将A的堆缓存门牌号赋值给了B,A和B存储的是同两个门牌号,对准的是同两个内容,因此B的改变当然会引起A的改变。

浅复本的形式

间接赋值

第一种形式就是上面所写代码中的将对象门牌号间接进行赋值。

var A={ name:”martin”, data:{num:10} }; var B={}; B=A; B.name=”lucy”; console.log(A.name); //”lucy”,A中name属性已改变

Object.assign(target,source)

这是ES6中新增的对象方法,对它不了解的见ES6对象新增方法,它可以实现第一层的“深复本”,但无法实现多层的深复本。

以当前A对象进行说明

第一层“深复本”:就是对于A对象下所有的属性和方法都进行了深复本,但当A对象下的属性如data是对象时,它复本的是门牌号,也就是浅复本,这种复本形式还是属于浅复本。

多层深复本:能将A对象下所有的属性,及时属性是对象,也能够深复本出来,让A和B相互独立,这种叫才叫深复本。

var A={ name:”martin”, data:{num:10}, say:function(){ console.log(“hello world”) } } var B={} Object.assign(B,A); //将A复本到B B.name=”lucy”; console.log(A.name); //martin,发现A中name并没有改变 B.data.num=5; console.log(A.data.num); //5,发现A中data的num属性改变了,说明data对象没有被深拷贝

浅复本总结

间接赋值:这种形式实现的就是纯粹的浅复本,B的任何变化都会反映在A上。

Object.assign():这种形式实现的实现的是单层“深复本”,但不是意义上的深复本,对深层还是实行的浅复本。

深复本

当B复本了A的统计数据,且当B的改变不会导致A的改变时,此时叫B深复本了A,比如:

//深复本 var A={ name:”martin”, data:{num:10}, say:function(){ console.log(“hello world”) } } //开辟了两个新的堆缓存门牌号,假设为placaA var B={}; //又开辟了两个新的堆缓存门牌号,假设为placeB B=JSON.parse(JSON.stringfy(A)); B.name=”lucy”; console.log(A.name); //martin

通过JSON对象方法实现对象的深复本,我们可以看到其中B.name值的改变并没有影响A.name的值,因为A和B分别对准相同的堆缓存门牌号,因此两者互不影响。

深复本的形式

认知了厚薄复本,接下来说一下深复本的几种形式。

首先假设两个已知的对象A,然后需要把A深复本到B。

var A={ name:”martin”, data:{num:10}, say:function () { console.log(“say”); } }; var B={};

递归赋值

function deepCopy(A,B) { for(item in A){ if(typeof item==”object”){ deepCopy(item,B[item]); }else{ B[item]=A[item]; } } } deepCopy(A,B); B.data.num=5; console.log(A.data.num); //10,A中属性值并没有改变,说明是深复本

通过这种形式能实现深层复本,而且能自由控制复本是如何进行的,如:当B中有和A同名的属性,要不要重新赋值?这些都可以进行控制,但代码相对复杂一些。

JSON.parse()和JSON.stringify

var B=JSON.parse(JSON.stringify(A)); B.data.num=5; console.log(A.data.num); //10,A中属性值并没有改变,说明是深复本

用这种形式实现深复本的时候要 注意 , 函数是无法进行复本的,会被丢失 ,上述代码中B也并没有复本出A中的say函数,这和JSON.stringify方法的规则有关系,它在序列化的时候会间接忽略函数,因此最后A中的say函数没有被复本到B,关于JSON.stringify序列化的具体规则见JSON.stringify指南。

深复本总结

递归:使用递归进行深复本时比较灵活,但代码较为复杂;

JSON对象:JSON对象方法实现深复本时比较简单,但当复本对象包含方法时,方法会被丢失;

因此使用者可按自身的使用场景来选择复本形式

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务