深拷貝和淺拷貝(實用版)

堆內存和棧內存

一、在js中,變量的儲存對象主要有倆種方式:堆內存和棧內存;
二、 js中 數據類型有 值類型(基本數據類型){String number boolean null(null雖然作爲一個object類型,但也是基本數據類型) undefined symbol}和引用數據類型{object array function}
三、 棧內存主要存儲的是值類型(基本數據類型)以及堆內存中對象變量的指針;
四、堆內存主要存儲引用數據類型;
五、棧內存是有序存儲,容量小,系統分配率高;堆內存首先要分配存儲區域,之後再把這個區域的位置(指針)存儲到棧內存中;這就是爲啥js在訪問對象時,得根據地址(指針)去獲取對象得值;

深拷貝和淺拷貝都是圍繞堆內存和棧內存展開的,一個是處理堆內存中得值,一個是處理棧內存中的指針;

六、在棧內存中,基本數據類型都是相互獨立的,互不影響;而在堆內存中,一個引用類型可以有多個指針,這些指針都指向同一個堆內存中的對象;某一個指針對這個引用類型的修改,其他指針指向的是被修改後的引用類型;

淺拷貝和深拷貝都是針對引用數據類型

七、淺拷貝只是複製指針,不復制引用數據類型本身;
八、深拷貝會複製引用數據類型本身,倆個對象一摸一樣;新舊對象互不影響;

寫一個淺拷貝方法
function lightcopy (zrobj) {
    var obj = {};
    //拷貝一層,深層次的對象就拷貝引用
    for(var i in zrobj){
        obj[i] = zrobj[i]
    }
    return obj;
}

var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
} 

var nowCopyObjOne = lightcopy(obj);
var nowCopyObjTwo = lightcopy(obj);
console.log(nowCopyObjOne.a)  //1
console.log(nowCopyObjOne.b.a)  //2
console.log(nowCopyObjOne.b.fn())  //2
console.log(nowCopyObjTwo.a)  //1
console.log(nowCopyObjTwo.b.a)  //2
console.log(nowCopyObjTwo.b.fn())  //2

nowCopyObjOne.b.a = '我被nowCopyObjOne修改啦'

console.log(nowCopyObjOne.a)  //1
console.log(nowCopyObjOne.b.a)  //我被nowCopyObjOne修改啦
console.log(nowCopyObjOne.b.fn())  //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.a)  //1
console.log(nowCopyObjTwo.b.a)  //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.b.fn())  //我被nowCopyObjOne修改啦
用ES6裏面的Object.assign()《本身是用來合併多個對象》實現一個淺拷貝

Object.assign(target, …sources) target爲目標對象。sources爲任意多個源對象。

var a = {
    name:'睿睿'
};
var b = {
    age:'18'
};
var c = {
    gender:'男'
};
var d = {
    position:'程序猿'
};
Object.assign(b,c,d);
console.log(b)//{age: "18", gender: "男", position: "程序猿"}
//該方法會修改傳入的第一個對象;所以要實現淺拷貝的話 第一個參數傳{};
var dCopy = Object.assign({} , a , b , c , d)
//如果有重複的屬性,會被右邊的值覆蓋,按照參數從左到右的順序
//此時,由於Object.assign(b,c,d);  所以 b已經成爲{age: "18", gender: "男", position: "程序猿"}
//所以:c 和 d 裏面的屬性會覆蓋b中的屬性
console.log(dCopy)//{name: "睿睿", age: "18", gender: "男", position: "程序猿"}
寫一個深拷貝的方法(遞歸)
function deepClone(obj) {
    var deepObj = {};
    for(var key in obj) {
        //判斷對象是否有下一級
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            //如果下一級也是對象
            if (typeof obj[key] === 'object') {
                //遞歸
                deepObj[key] = deepClone(obj[key]); 
            } else {
                deepObj[key] = obj[key];
            }
        }
    }
    return deepObj;
}
var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
} 
var deepCopyobjOne = deepClone(obj)
var deepCopyobjTwo = deepClone(obj)
console.log(deepCopyobjOne.a)  //1
console.log(deepCopyobjTwo.a)  //1

deepCopyobjOne.a='3';

console.log(deepCopyobjOne.a)  //3
console.log(deepCopyobjTwo.a)  //1
用JSON.parse和JSON.stringify實現深拷貝
var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
}
var deepObjJSONOne = JSON.parse(JSON.stringify(obj));
var deepObjJSONTwo = JSON.parse(JSON.stringify(obj));
console.log(deepObjJSONOne.a)  //1
console.log(deepObjJSONTwo.a)  //1

deepObjJSONOne.a='3';

console.log(deepObjJSONOne.a)  //3
console.log(deepObjJSONTwo.a)  //1

完!
(方法很實用,懂的比較淺,有問題多多指出;謝謝)

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