上星期再次研究了一下以前不太清楚的深度克隆,經過連續的寫了3次之後終於清晰了一點,記錄一下思路。
show me my code
var user={
name:'姓名',
gender:'性別',
Tags:['標籤1','標籤2']
}
顧名思義,淺度克隆就是指複製啦~
Object.prototype.clone=function(){
var newObj={};
for(var key in this){
if(this.hasOwnProperty(key)){
newObj[key]=this[key];
}
}
return newObj;
};
var jack=user.clone();
jack.name='jack';
jack.gender='男';
jack.Tags.push('男神');
結果如下:
ok,我們這裏就完成了淺度克隆了,由於我是對整個Object的原型寫函數來繼承的,所以我在循環內判斷了一下屬性是否爲自身的自有屬性,是的話才能複製,解決了會繼承複製clone函數的小問題,如果不判斷,在結果中會出現clone函數,因爲我們這裏是對所有對象原型寫的繼承函數。
那麼淺度克隆的問題在哪了,接下來大家就會看到了
假如這時候又多了個妹子
var mary=user.clone();
mary.name='mary';
mary.gender='女';
mary.Tags.push('女神');
結果如下:
問題顯而易見,圖中對象順序依次爲mary、jack、原對象,很明顯我們想要的效果其實是jack在Tags中是['標籤1','標籤2','男神']
,mary的Tags是['標籤1','標籤2','女神']
,而現狀是全部的Tags都變爲了['標籤1','標籤2','男神','女神']
,原對象也是,而造成這個問題的原因就是數組是引用類型的= =…這個是基礎知識,我想大家都是知道的,所以簡單的賦值只是將數組地址賦給了新對象而已,真正引用和更改的仍然是原對象中的數組;
那麼解決方法已經很明顯了,判斷一下是否爲引用類型,將引用類型內的元素都賦值就好,利用遞歸函數就可以巧妙的解決,這就是深度克隆的原理了,下面上深度克隆demo:
Object.prototype.deepClone=function(){
var newObj = this.constructor == Array?[]:{};//判斷克隆對象構造函數爲數組
for(var key in this){
if(this.hasOwnProperty(key)){
if(typeof this[key] == "object"){
newObj[key] = this[key].deepClone();
}
else{
newObj[key] = this[key];
}
}
}
//如果是構造函數的情況請加上,不然父深度克隆後的父鏈並不會指向原構造函數而是Object
// newObj.__proto__ = this.__proto__;
return newObj;
};
var kalista = user.deepClone();
kalista.name='卡利斯塔';
kalista.gender='女';
kalista.Tags.push('LOL');
console.log(kalista);
var jugg=user.deepClone();
jugg.name='劍聖';
jugg.gender='男';
jugg.Tags.push('DOTA');
console.log(jugg);
結果如下:
完成~我寫的函數還是比較簡單的,我就不說明了,原理在上面也說過了,實現過程就跟原理所說的一樣,需要注意的只是數組的typeof爲object與記得遞歸後的賦值而已,over~