Js中對象的深拷貝和淺拷貝

淺拷貝:只拷貝對象的基礎屬性值,對屬性值爲對象或數組的屬性則拷貝指針。 
深拷貝:拷貝對象的所有屬性作爲一個全新的對象。拷貝前後的對象互不影響。

淺拷貝僅僅是指向被複制的內存地址,如果原地址中對象被改變了,那麼深拷貝出來的對象也會相應改變。

一、對象引用

對象引用容易理解,直接賦值,修改複製後的數組,原對象會隨之改變。

//對象引用
var boy = {
	age:18
    }
var girl = boy;
console.log(boy === girl);//true
girl.age = 20;
console.log(boy.age);//20 

理解:使用“=”進行賦值,girl和boy指向了同一內容地址,修改一個,另一個也會修改。

二、淺拷貝

使用Object.assign() 方法用於將所有可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。

//淺拷貝
var boy = {
	age:18
    }
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.age = 20;
console.log(boy.age);//18

理解:上述代碼將原始對象拷貝到一個空對象,就得到原始對象的克隆,原對象和拷貝對象指向不同的內存地址,修改原對象和克隆對象,互補影響。

var boy = {
	age:18,
	address:{
		home:'北京'
	}
}
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.address.home = '上海';
console.log(boy.address.home);//上海 

理解:上述代碼將原始對象拷貝到一個空對象,就得到原始對象的克隆。因爲Object.assign()只是淺拷貝girl.address是對棧對象的引用,因此內層對象的修改會影響原始對象。

三、深拷貝

1、JSON.parse()與JSON.stringify()深拷貝

可以通過JSON對象的方法,來進行對象的深拷貝,代碼如下:

//純數據json對象的深度克隆
function deepClone(obj) {
     return JSON.parse(JSON.stringify(obj));
}

理解:通過對象符串化和字符串對象化進行對象的拷貝。此方法只使用與純JSON對象的深拷貝

2、對象遍歷

//包含其他負責的內容 date對象 null undefined
var obj1={
	name:"張三",
	age:20,
	height:[12,26,46],
	address:{
	    home:'北京'
	},
	birthday:new Date(),
	father:null,
	mother:undefined,
	school:[
			{
				middleschool:'北大附中',
			},
			{
				university:'清華大學',
			}
		]
	}
	function clone(obj) { 
	    if(obj === null) return null 
	    if(typeof obj !== 'object') return obj;
	    if(obj.constructor === Date) return new Date(obj); 
	    if(obj.constructor === RegExp) return new RegExp(obj);
	    var newObj = new obj.constructor ();  //保持繼承鏈
	    for (var key in obj) {
		 if (obj.hasOwnProperty(key)) {   //不遍歷其原型鏈上的屬性
		      var val = obj[key];
		      newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除與函數名的耦合
		  }
            }  
            return newObj;  
	}; 
        console.log(obj1);
    console.log(clone(obj1));

理解:

(1)、用 new obj.constructor ()構造函數新建一個空的對象,可以保持原形鏈的繼承;

(2)、用obj.hasOwnProperty(key)來判斷屬性是否來自原型鏈上,因爲for..in..也會遍歷其原型鏈上的可枚舉屬性。

(3)、函數用到遞歸算法,在函數有名字,而且名字以後也不會變的情況下,這樣定義沒有問題。但問題是這個函數的執行與函數名 factorial 緊緊耦合在了一起。爲了消除這種緊密耦合的現象,需要使用 arguments.callee

參考:https://www.cnblogs.com/wangyulue/articles/7684515.html
























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