淺談JS中物件的淺複製和深複製

喜鹿發表於2019-07-09

基礎知識:
JS物件:指向記憶體中某個位置的指標,指標是可變的,也就是說可以被重新賦值,所以說,複製指標,只是將兩個指標指向記憶體中的同一地址,也可以說是地址複製。

//複製指標
var obj = { a: "123" };
var newObj = obj;

在上面程式碼中,物件 obj和 newObj都能隨著對方的變化而變化,所以要根據實際情況來複制物件。

一、淺複製
如果要操作的物件擁有的屬性都是值型別,那麼可以使用擴充套件語法或 Object.assign()

var obj = { foo: "foo", bar: "bar" };
var newObj = { ...obj };   // Object { foo: "foo", bar: "bar" }
var newObj = Object.assign({}, obj);    // Object { foo: "foo", bar: "bar" }

補充知識:Object.assign()是ES6新加的介面,主要用來合併多個JS物件

  1. Object.assign() 第一個引數是目標物件,後面的都是源物件。 Object.assign (target, source1,source2, source3, …);
  2. 如果源物件與目標物件有相同的屬性名,或源物件中有相同的屬性名,後面的會覆蓋前邊的值
  3. 如果引數傳入的不是Object,會轉成Object
  4. null和undefined 不能作為引數傳入,因為null和undefined 不能轉成Object
  5. 如果發生的值是一個物件,Object.assign的處理方法是直接替換,而不是新增

Object.assign()內容詳情可檢視:MDN中對Object.assign()的描述

一個小細節注意一下:從使用效果上來看,Object.create()建立的新物件有點類似淺複製,只不過新物件和原物件是一種繼承關係,而Object.assign()建立的新物件和原物件是彼此獨立的。

var obj = { a: "123", b: { c: "321"}};
for(let p in obj){
	newObj[p] = obj[p];
}

上述程式碼只進行了對物件第一層的複製,物件裡引用型別則進行的是地址複製,這一操作也是淺複製

二、深複製
1、有限制的深複製(先把物件序列化為字串,然後再將其反序列化)

var obj = { a: "123", b: "321"};
var newObj = JSON.parse(JSON.srtingify(obj));

限制:只在物件中包含可系列化值,且沒有迴圈引用的情況下使用
日期物件不可以被序列化,JSON.parse()後為字串而不是日期

2、限制較少的深複製(使用遞迴思想)

function deepCopy(obj){
	var newObj = {};
	for(let p in obj){
		if(!(p instanceof object) || (typeof p === 'function)){
			newObj[p] = objt[p];
		}else{
			newObj[p] = deepCopy(obj[p]);
		}
	}
	return newObj;
}

所以可以得出一種較為通用的JS複製物件的方法:

function deepCopy(obj){
	var newObj =obj.constructor === Array ? [] : {};
	newObj.constructor = obj.constructor;
	if(typeof obj !== 'object'){
		return ;
	}else if(window.JSON) {  //若需考慮特殊資料型別,比如正則函式等,則去掉此else if
		newObj = JSON.parse(JSON.stringify(obj));
	}else {
		for(let p in obj){
			if(obj[p].constructor === regExp || obj[p].constructor === Date){
				newObj[p] = obj[p];
			}else if(typeof p === 'object'){
				newObj[p] = deepCopy(obj[p]);
			}else{
				newObj[p] = obj[p];
			}
		}
	}
	return newObj;
}

學習參考:
https://segmentfault.com/a/1190000018903274#articleHeader1
https://baijiahao.baidu.com/s?id=1625060204489718788&wfr=spider&for=pc

這是我第一次寫學習總結文章,若有不對的地方,麻煩大佬們指出錯誤,我們共同進步呀~~

相關文章