javascript
javascript深拷贝和浅拷贝
在JavaScript中,存在著這樣的兩種拷貝方式。分別是:深拷貝和淺拷貝,這兩種拷貝在實(shí)際中非常的常見(jiàn),如果讀者是一個(gè)閱讀源碼的愛(ài)好者,相信多多少少對(duì)深拷貝和淺拷貝有所了解。
?
一、淺拷貝
淺拷貝在現(xiàn)實(shí)中最常見(jiàn)的表現(xiàn)在賦值上面,例如
<!DOCTYPE?html><html?lang="en"><head><meta?charset="UTF-8"><title>測(cè)試</title></head><body><script?type="text/javascript">//第一個(gè)數(shù)組var?test=["1","2","3"];????????//第二個(gè)數(shù)組var?test2=[];test2=test;test2[1]="two";console.log(test);//運(yùn)行的結(jié)果是["1","two","3"]</script></body></html>
從上面的例子,我們修改test2數(shù)組的值,最后打印test數(shù)組,發(fā)現(xiàn)test也跟著改變了。
其實(shí)這個(gè)就是一個(gè)最淺的淺拷貝,相當(dāng)于test2=test這個(gè)階段是在將test數(shù)組中的存儲(chǔ)地址索引賦值給test2數(shù)組,所以兩個(gè)數(shù)組都是指向同一塊存儲(chǔ)地址中去。
除了這種方法可以實(shí)現(xiàn)淺拷貝,還有使用slice和concat進(jìn)行淺拷貝
例如:我們測(cè)試一次slice這個(gè)方法
?
<script?type="text/javascript">????var?arr=["demo1","demo2","demo3"];????var?arr2=arr.slice(0);arr2[1]="test";console.log(arr);//["demo1","demo2","demo3"]console.log(arr2);//["demo1","test","demo3"]</script>
從上面的例子我們可以看出,使用slice方法對(duì)數(shù)組進(jìn)行了深度拷貝,
同理,concat的用法如下
?
<script?type="text/javascript">????var?arr=["demo1","demo2","demo3"];????var?arr2=arr.concat();arr2[1]="test";console.log(arr);//["demo1","demo2","demo3"]console.log(arr2);//["demo1","test","demo3"]</script>
為何這樣已經(jīng)算得上是深拷貝的東西,我又稱之為淺拷貝呢?
其實(shí)使用slice和concat這兩個(gè)方法部分都是不可以拷貝如下的這種情況的:
運(yùn)行如下的代碼:
?
<script?type="text/javascript">????var?arr?=?[1,3,[4,7,65,9]];????var?arr1=arr.slice(0);arr1[2][2]=2;console.log(arr1[2][2]);console.log(arr);</script>
?
或者是如下的這一段代碼:?
<script?type="text/javascript">????var?arr?=?[1,3,[4,7,65,9]];????var?arr1=arr.concat();arr1[2][2]=2;console.log(arr1[2][2]);console.log(arr);</script>
?
我們都可以看到,我們拷貝了arr的值,然后同時(shí)修改arr1的值,我們可以看到arr也被修改了。
所以對(duì)于Slice和concat這兩個(gè)方法來(lái)說(shuō)都是淺拷貝,只能拷貝數(shù)組中的第一層
另外除了可以對(duì)數(shù)組進(jìn)行淺拷貝,同樣的我們也可以對(duì)JSON數(shù)據(jù)進(jìn)行淺拷貝
assign這個(gè)方法可以對(duì)object對(duì)象進(jìn)行復(fù)制,但是這種拷貝是淺拷貝跟直接賦值卻又是不一樣的。
assign其中接受兩個(gè)參數(shù),第一個(gè)參數(shù)指代的是拷貝之后需要修改的內(nèi)容,第一個(gè)參數(shù)指代的是要拷貝的內(nèi)容
<script?type="text/javascript">????var?obj?=?{?a:?{a:?"hello",?b:?21}?};?var?initalObj?=?Object.assign({b:{"test":1111}},?obj);?initalObj.a.a?=?"changed";?console.log(obj);console.log(initalObj);console.log(obj.a.a);?//?"changed"console.log(obj===initalObj);//false</script>
?
運(yùn)行上面的代碼可以看到,obj 里面的值也被修改了
?
二、深拷貝
?最簡(jiǎn)單的深拷貝就莫過(guò)于使用JSON對(duì)象提供的方法。
?我們先來(lái)個(gè)例子測(cè)試一下:
?
<script?type="text/javascript">????var?json={????????"a":"test",????????"b":"test1"};????var?b=JSON.parse(JSON.stringify(json));b.a="demo";console.log(json);//{"a":"test","b":"test1"}</script>
?
我們修改了b中的值,但是打印json對(duì)象發(fā)現(xiàn)沒(méi)有被修改到,這個(gè)已經(jīng)就是深度拷貝的。
但是轉(zhuǎn)換后的原來(lái)的值類型會(huì)出現(xiàn)丟失,也就是最后的類型一定是Object類型。
說(shuō)道深拷貝,就不能不提Jquery中中的extend方法,這個(gè)方法如果是有學(xué)習(xí)制作插件的同學(xué)應(yīng)該都會(huì)知道,這個(gè)方法用于生成一個(gè)全新的JSON對(duì)象值。
其實(shí)這個(gè)本身就是一種深拷貝的應(yīng)用,具體的代碼如下:
?
????<script?src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script><script?type="text/javascript">????????var?arr=["test",["demo1","demo2"]];????????var?arr1=$.extend({},arr);arr[1][0]=1;console.log(arr1);????</script>
?
上面的代碼運(yùn)行的時(shí)候,我們可以看到即使是數(shù)組也是同樣可以深度拷貝的。
轉(zhuǎn)載于:https://blog.51cto.com/13111614/1946186
總結(jié)
以上是生活随笔為你收集整理的javascript深拷贝和浅拷贝的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 社交背水一战?校园日记背后,支付宝野心你
- 下一篇: NodeJS-queryString