手動實現一個深拷貝

爲何要用深拷貝?

小夥伴們都知道,js中的對象屬於引用類型,單純的用等號賦值,其實複製的是引用地址,真正指向的仍是堆內存中同一個值,當一個值的內部屬性變化時,另外一個值因爲指向的是堆內存中的同一個值,因此也會發生變化。這每每是咱們不想要的結果,我也在項目中由於這個吃過大虧,因此一塊兒來討論討論吧!數組

如何手動實現一個深拷貝?

方法1:JSON.stringify ,JSON.parse

經過JSON.stringify,JSON.parse能夠實現深拷貝,可是有個坑得注意下,在序列化JavaScript對象時,全部函數和原型成員會被有意忽略。看下面這個案例:bash

var a = {
    name:"西瓜",
    run:function(){
        console.log(123)
    }
}
console.log(JSON.parse(JSON.stringify(a)));
複製代碼

能夠看出,在拷貝的過程當中,對象中的 run方法不見了。

方法2:遞歸

話很少說,直接上代碼:函數

//主入口函數
function deepCopy(obj){
    if(typeof obj === "object"){
        //是一個數組
        if(Array.isArray(obj)){
            return copyArray(obj);
        }else{
            //是一個對象
            return copyObj(obj);
        }
    }
}

//若是是對象類型的,執行該函數
function copyObj(obj){
    var newObj = {};
    for(let key in obj){
        if(typeof obj[key] === "object"){
			//obj[key]仍是屬於object類型的話,遞歸執行deepCopy
            newObj[key] = deepCopy(obj[key]);
        }else{
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

//若是是數組類型類型的,執行該函數
function copyArray(array){
    var newArr = [];
    array.forEach((item,index)=>{
		//item仍是屬於object類型的話,遞歸執行deepCopy
        if(typeof item === "object"){
            newArr.push(deepCopy(item));
        }else{
            newArr.push(item);
        }
    });
    return newArr;
}
//測試
var testObj = [{
        name:"西瓜",
        info:{
            age:10,
            adress:"杭州"
        }
    },
    "哈哈哈哈哈",
    {
        run:function(){
            console.log(123)
        }
    }
];

var deepObj = deepCopy(testObj);

testObj[1] = "我改變了數組裏面的一個值";

console.log(testObj);

console.log(deepObj);
複製代碼

運行結果以下:測試

結果中看到,deepObj是使用深拷貝函數後獲得的結果,在這以後去修改testObj的值,deepObj的值並無發生改變。說明深拷貝成功啦! ###總結 在實現深拷貝的過程當中,也能夠複習一下遞歸的知識,仍是挺好的!小夥伴們也去試試吧!ui

相關文章
相關標籤/搜索