談談JS中的深度拷貝

談談JS中的淺拷貝這篇文章中,我們提到了JS中的淺拷貝,也知道淺拷貝產生的原因,以及淺拷貝只在引用型數據類型中出現,那麼今天我們就來談談如何進行深度拷貝!
方法一:數組的concat與slice方法

var a = [1, 2, 3, 4, 5];
var b = a.slice();
// var b = a.concat();
b[0] = 12;
console.log(a);   //輸出 [1, 2, 3, 4, 5]
console.log(b);   // 輸出[12, 2, 3, 4, 5]

我們發現JS數組的這兩個方法都能對數組進行深度複製。
缺點:
1、slice和concat方法只能用於數組
2、即使是像下面這種格式的也不能進行深度拷貝,因爲第二層是對內存的引用

var a = [{
	x: 1,
	z: {
		b: 3
	}
}]
var c = a.slice();
// var c = a.concat();
c[0].x = 11;
c[0].z.b = 13;
console.log(a);  // a[0].x=11,  a[0].z.b=13
console.log(c);  // c[0].x=11,  c[0].z.b=13

方法二:ES6的解構方法

var a = [1, 2, 3, 4];
var b = [...a];
b[0] = 11;
console.log(a);  // 輸出[1, 2, 3, 4]
console.log(b);  // 輸出[11, 2, 3, 4]

缺點:只能解構數組,同樣不能解構複雜的json,因爲第二層同樣是對內存的引用。

方法三:遞歸遍歷複製

// 遞歸拷貝函數
function deepClone(obj){
    let objClone = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === "object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)) {
                //判斷ojb子元素是否爲對象,如果是,遞歸複製
                if(obj[key]&&typeof obj[key] === "object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,簡單複製
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
} 

var a = [{
	x: 1,
	z: {
		b: 3
	}
}]
var c = deepClone(a);
c[0].x = 11;
c[0].z.b = 13;
console.log(a);  // 輸出a[0].x=1,  a[0].z.b=3
console.log(c);  // 輸出c[0].x=11,  c[0].z.b=13

方法四:parse和stringify方法

// stringify和parse的拷貝函數
function deepClone(val) {
	var obj = Array.isArray(val) ? [] : {};
	// 轉化爲字符串
	obj = JSON.stringify(val);
	// 返回對象
	return JSON.parse(obj);
}

var a = [{
	x: 1,
	z: {
		b: 3
	}
}]
var c = deepClone(a);
c[0].x = 11;
c[0].z.b = 13;
console.log(a);  // a[0].x=1,  a[0].z.b=3
console.log(c);  // c[0].x=11,  c[0].z.b=13

方法五:jq的$.extend方法

/**

    $.extend([deep], target, object1[,objectN])
    deep: 拷貝類型,true爲深度拷貝,false爲淺拷貝
    target:目標對象,其他對象將被附加到該對象上
    object1[,objectN]:需要拷貝的對象,可以是多個對象

*/
var a = [{
	x: 1,
	z: {
		b: 3
	}
}]
var c = $.extend(true, [], a);
c[0].x = 11;
c[0].z.b = 13;
console.log(a);  // a[0].x=1,  a[0].z.b=3
console.log(c);  // c[0].x=11,  c[0].z.b=13

以上爲常用的五種深度拷貝方法,希望對大家有所幫助,個人技術有限,如果大家還有其他更好的方法,歡迎留言,我會及時更新的,祝大家新年快樂!

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