對深拷貝和淺拷貝的全面理解

關於深拷貝和淺拷貝

從原理看:html

  • 淺拷貝:拷貝一層,對象級別的則拷貝引用
  • 深拷貝:拷貝多層,每一個層級的屬性都會拷貝

從現象看:
A複製了B,B被修改後,數組

  • A隨B變化而變化->淺拷貝
  • A不變->深拷貝

深拷貝針對的s複雜的object類型數據
∴如直接賦值的單層拷貝,如b=a,b雖然不受a的影響,可是這也不算作深拷貝
現象只是做爲方便理解的一個參考,真正的判斷標準仍是要從原理上看函數


數據類型分爲:spa

  1. 基本數據類型(7種):namevalue都存儲在棧內存中
  2. 引用數據類型:name->棧內存,值->堆內存,棧內存會提供一個引用的地址指向堆內存的值

clipboard.png

當b=a進行拷貝時,b複製的是a的引用地址,並非堆裏面的值,因此這便形成了當a發生改變,b也會隨之改變的淺拷貝.net


實現淺拷貝的方法:
1、 直接複製指針

//基本數據類型
var arr = [1, 2, 3, '4'];

var arr2 = arr;
arr2[1] = "test"; 
console.log(arr); // [1, "test", 3, "4"]
console.log(arr2); // [1, "test", 3, "4"]
//改變其中一個對象的屬性值,兩個對象都發生了改變 
//obj和obj2兩個變量都指向同一個指針,賦值時只是複製了指針地址,它們指向同一個引用,∴當咱們改變其中一個的值,另外一個變量的值也會隨之改變


----------


//對象級
function Clone(obj1){
    var obj2 ={};
    for(var i in obj1)
    {
        obj2[i]=obj1[i];
    }
    return obj2;
}

淺拷貝只是拷貝了一層,除了對象是拷貝引用類型,其餘的都是直接將值傳遞,有本身的內存空間code

2、ES6中的Object.assign()方法
該方法能夠把任意多個的源對象自身的可枚舉屬性拷貝給對象,而後返回目標對象htm

Object.assign(目標對象,任意多個源對象)
var obj1 = {
    a: "hello",
    b: {
        a: "hello",
        b: 21}
};
 
var cloneObj1= Object.assign({}, obj1);
cloneObj1.a = "changed";
cloneObj1.b.a = "changed";
console.log(obj1.a);  //hello
console.log(obj.b.a); // "changed"

若是對象只有一層,這個函數能夠做爲深拷貝的方法對象

var obj2 = { a: 10, b: 20, c: 30 };
var cloneObj2 = Object.assign({}, obj2);
cloneObj2.b = 100;
console.log(obj2);
// { a: 10, b: 20, c: 30 } <-- 沒有改變,實現了深拷貝
console.log(cloneObj2);
// { a: 10, b: 100, c: 30 }

若想實現深拷貝,就須要在堆中開闢一個內存,用來存放b的值。blog

方法1、手動複製
將A對象項的屬性逐個負責給另外一個對象的屬性

var ob1 = {a:1,b:2,c:3};
var ob2 = {a:ob1.a,b:ob1.b,c:ob1.c};
ob1.a = 0;
ob2.b = 0;
console.log(ob1);//023
console.log(ob2);//103

這樣很麻煩,且本質上不能算做深拷貝,當ob1內嵌套對象c時,ob1和ob2將共享c,當改變c的屬性時,ob1ob2將都發生改變

方法2、將對象經過JSON方法轉成字符串再轉回來
能夠實現真正的深拷貝,可是隻能用於能夠轉成JSON格式的對象,function沒法轉換成JSON,就不可以使用
∴此方法會捨棄對象的構造函數

var ob1 ={c:{a:1,b:2}};
var ob2 =JSON.parse(JSON.stringfy(ob1));
//用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象

方法3、遞歸拷貝

function deepClone(obj1,obj2){
    var obj = obj2|| {};//若是obj存在則定義爲obj2,不然創建空對象
        for(var i in obj1){//遍歷原對象
        if(typeof obj1[i] === 'object'){//若是當前元素是對象
        
            obj[i] = Array.isArray(obj1[i]) ?[]:{};//判斷是數組仍是對象 
            deepClone(obj1[i],obj[i]);//利用遞歸逐層遍歷直到最後一層
        }
        else{

            obj[i] = obj1[i];//賦值
        }
        
    }
    return obj;

}

var str = {};
var obj = { a: {a: "Leemo", b: 19980228} };
deepClone(obj, str);
console.log(str.a);

方法4、使用Object.create()方法

var Obj2 = object.create(Obj1);
//實現Obj2深拷貝Obj1

參考文檔:
文檔1
文檔2

相關文章
相關標籤/搜索