淺拷貝(shellow copy)
先看下邊一個例子:
Object.prototype.clone = function () {
var newObj = {},
self = this;
for (var i in self) {
newObj[i] = self[i];
}
return newObj;
}
var obj = {
name:"老李頭",
hobby:["敲代碼","壓馬路"]
}
var _obj = obj.clone();
obj.hobby.push("打籃球");
console.log(obj.hobby);//["敲代碼", "壓馬路", "打籃球"]
console.log(_obj.hobby);//["敲代碼", "壓馬路", "打籃球"]
就像我們看到的,淺拷貝只能復制基本類型的屬性,而對於共享對象類型的屬性則沒有辦法。
深拷貝 (deep copy)
在使用深拷貝復制對象時,由於數據類型的不確定性,可能為對象,數組,函數,也可能是以上幾種的嵌套。這個時候我們就需要借助遞歸。
Object.prototype.clone = function () {
var self = this,
newObj = {};
for(var i in self ){
if( typeof (self[i]) == "object" || typeof (self[i]) == "function"){
newObj[i] = self[i].clone();
}else{
newObj[i] = self[i];
}
}
return newObj;
}
Array.prototype.clone = function () {
var self = this,
newArr = [];
for(var i=0,len=self.length;i<len;i++){
if( typeof (self[i]) == "object" || typeof (self[i]) == "function"){
newArr [i] = self[i].clone();
}else{
newArr [i] = self[i];
}
}
return newArr;
}
Function.prototype.clone = function () {
var self = this,
newFn = function () {
return self.apply(this,arguments);
};
for(var i in self){
newFn[i] = self[i];
}
return newFn;
}
var obj = {
name: 'byvoid',
likes: ['node'],
display: function() {
console.log(this.name);
},
};
var newObj = obj.clone();
newObj.likes.push('python');
console.log(obj.likes); // 輸出 [ 'node' ]
console.log(newObj.likes); // 輸出 [ 'node', 'python' ]
console.log(newObj.display == obj.display); // 輸出 false
上面這個實現看起來很完美,它不僅遞歸地復制了對象復雜的結構,還實現了函數的深拷貝。這個方法在大多數情況下都很好用,但有一種情況它卻無能為力,例如下面的代碼:
var obj1 = {
ref:null
};
var obj2 = {
ref:obj1
};
obj1.ref = obj2;
這段代碼的邏輯非常簡單,就是兩個相互引用的對象。當我們試圖使用深拷貝來復制obj1 和 obj2 中的任何一個時,問題就出現了。因為深拷貝的做法是遇到對象就進行遞歸復制,那么結果只能無限循環下去。對於這種情況,簡單的遞歸已經無法解決。
