在JavaScript中,存在着這樣的兩種拷貝方式。分別是:深拷貝和淺拷貝,這兩種拷貝在實際中很是的常見,若是讀者是一個閱讀源碼的愛好者,相信多多少少對深拷貝和淺拷貝有所瞭解。javascript
淺拷貝在現實中最多見的表如今賦值上面,例如css
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>測試</title> </head> <body> <script type="text/javascript"> //第一個數組 var test=["1","2","3"]; //第二個數組 var test2=[]; test2=test; test2[1]="two"; console.log(test);//運行的結果是["1","two","3"] </script> </body> </html>
從上面的例子,咱們修改test2數組的值,最後打印test數組,發現test也跟着改變了。html
其實這個就是一個最淺的淺拷貝,至關於test2=test這個階段是在將test數組中的存儲地址索引賦值給test2數組,因此兩個數組都是指向同一塊存儲地址中去。java
除了這種方法能夠實現淺拷貝,還有使用slice和concat進行淺拷貝jquery
例如:咱們測試一次slice這個方法json
<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方法對數組進行了深度拷貝,數組
同理,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>
爲什麼這樣已經算得上是深拷貝的東西,我又稱之爲淺拷貝呢?測試
其實使用slice和concat這兩個方法部分都是不能夠拷貝以下的這種狀況的:spa
運行以下的代碼:
<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的值,而後同時修改arr1的值,咱們能夠看到arr也被修改了。
因此對於Slice和concat這兩個方法來講都是淺拷貝,只能拷貝數組中的第一層
另外除了能夠對數組進行淺拷貝,一樣的咱們也能夠對JSON數據進行淺拷貝
assign這個方法能夠對object對象進行復制,可是這種拷貝是淺拷貝跟直接賦值卻又是不同的。
assign其中接受兩個參數,第一個參數指代的是拷貝以後須要修改的內容,第一個參數指代的是要拷貝的內容
<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>
運行上面的代碼能夠看到,obj 裏面的值也被修改了
最簡單的深拷貝就莫過於使用JSON對象提供的方法。
咱們先來個例子測試一下:
<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對象發現沒有被修改到,這個已經就是深度拷貝的。
可是轉換後的原來的值類型會出現丟失,也就是最後的類型必定是Object類型。
說道深拷貝,就不能不提Jquery中中的extend方法,這個方法若是是有學習製做插件的同窗應該都會知道,這個方法用於生成一個全新的JSON對象值。
其實這個自己就是一種深拷貝的應用,具體的代碼以下:
<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>
上面的代碼運行的時候,咱們能夠看到即便是數組也是一樣能夠深度拷貝的。
具體的解釋是:由於上面咱們已經說過數組類型其實就是一種object類型,那麼extend方法是用來對object類型進行深拷貝的,那麼也就是知足了數組的這一種狀況,固然博主是沒有去看源碼的,因此若是解釋與源碼有出入,望請指正。
說一說最後的一種實現深拷貝的方法吧,也就是遍歷原對象,並將原對象賦值給生成後的對象,具體的方式詳見: