javascript深拷貝和淺拷貝

在JavaScript中,存在着這樣的兩種拷貝方式。分別是:深拷貝和淺拷貝,這兩種拷貝在實際中非常的常見,如果讀者是一個閱讀源碼的愛好者,相信多多少少對深拷貝和淺拷貝有所瞭解。

 

一、淺拷貝

淺拷貝在現實中最常見的表現在賦值上面,例如

複製代碼

<!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也跟着改變了。

其實這個就是一個最淺的淺拷貝,相當於test2=test這個階段是在將test數組中的存儲地址索引賦值給test2數組,所以兩個數組都是指向同一塊存儲地址中去。

除了這種方法可以實現淺拷貝,還有使用slice和concat進行淺拷貝

例如:我們測試一次slice這個方法

 

複製代碼

<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這兩個方法部分都是不可以拷貝如下的這種情況的:

運行如下的代碼:

 

複製代碼

<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>

複製代碼

 

上面的代碼運行的時候,我們可以看到即使是數組也是同樣可以深度拷貝的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章