js
包含基本資料型別與引用資料型別兩種不同的資料型別的值,深拷貝與淺拷貝的概念只存在於引用資料型別。對於引用型別,淺拷貝是拷貝了指向這個物件堆記憶體的指標,是拷貝了對原物件引用,深拷貝是拷貝了該物件的所有屬性到乙個新的物件,若是原物件的某屬性依然引用了其他物件,那麼需要將原物件引用的其他物件一併進行深拷貝,並不斷遞迴進行。對於基本資料型別是不存在深拷貝與淺拷貝的概念的,如果將乙個基本資料型別變數的值賦值到另乙個變數,那麼新變數的值是對於原變數值的複製而不是引用,如果必須要按照深淺拷貝的概念理解的話,對於基本資料型別的複製可以理解為按值深拷貝。
原生方法實現淺拷貝,可以使用與
object.assign({}, obj)
等方式,主要是使用了
spread
操作符將物件表示式展開構造字面量物件的方式實現淺拷貝,對於object.assign({}, obj)
是執行了一次將可列舉屬性複製到目標物件並返回目標物件的操作。關於object.assign
是淺拷貝還是對於第一層是深拷貝之後是淺拷貝的說法,主要取決於如何理解淺拷貝與深拷貝的概念,假如同本文一樣認為只有引用型別才有淺拷貝與深拷貝的概念的話,那麼object.assign
就是淺拷貝;假如認為對於基本資料型別也有淺拷貝與深拷貝的概念的話,那麼如上文所述對於基本資料型別的拷貝可以理解為按值深拷貝,那麼關於object.assign
第一層是深拷貝,第二層及以後是淺拷貝的說法也是沒有問題的。
原生方法實現深拷貝,主要是使用json.parse()
與json.stringify()
,首先將物件序列化為json
字串,再將json
字串反序列化為物件,使用這種方式效率比較高,但是會有一些問題,對於迴圈引用的物件無法實現深拷貝,對於被拷貝的物件,如果物件中有屬性為date
物件,此種方式深拷貝會將時間物件轉化為字串;如果物件中有屬性為regexp
物件、error
物件,此種方式深拷貝會得到乙個空物件;如果物件中有屬性為function
物件、undefined
、symbol
值,此種方式深拷貝會忽略這些值;如果物件中有屬性為nan
、infinity
、-infinity
,此種方式深拷貝會將結果轉為null
。
function shallowcopy(target, origin)
function deepcopy(target, origin)
// 淺拷貝測試 將origin中屬性淺拷貝到target
var target = {}
var origin =
}shallowcopy(target, origin);
console.log(target, origin); // } }
origin.a.aa = 11;
console.log(target, origin); // } }
// 深拷貝測試 將origin中屬性深拷貝到target
var target = {}
var origin =
}deepcopy(target, origin);
console.log(target, origin); // } }
origin.a.aa = 11;
console.log(target, origin); // } }
對於淺拷貝,只需要處理被拷貝物件的所有的可列舉屬性進行賦值即可。
對於深拷貝,需要將基本資料型別進行賦值,然後對物件屬性進行遞迴處理。
function shallowcopy(target, origin)
function deepcopy(target, origin), origin[item]);
}else if(origin[item] instanceof array)else if(origin[item] instanceof date)else if(origin[item] instanceof regexp)else
}else
}return target;
}// 淺拷貝測試 將origin中屬性淺拷貝到target
var target = {}
var origin =
}shallowcopy(target, origin);
console.log(target, origin); // } }
origin.a.aa = 11;
console.log(target, origin); // } }
// 深拷貝測試 將origin中屬性深拷貝到target
var target = {}
var origin = ,
cc: [1, ],
dd: new date().gettime(),
ee: /./g
} }deepcopy(target, origin);
console.log(target, origin);
/* a: bb:
cc: [1, ] cc: [1, ]
dd: 1390318311560 dd: 1390318311560
ee: /./g ee: /./g
} }
*/origin.a.aa = 11;
origin.a.bb.bbb = 11;
origin.a.cc[0] = 11;
origin.a.cc[1].ccc = 11;
origin.a.dd = new date().gettime();
origin.a.ee = /./gi;
console.log(target, origin);
/* a: bb:
cc: [1, ] cc: [11, ]
dd: 1390318311560 dd: 1390318792391
ee: /./g ee: /./gi
} }
*/
「淺拷貝」與「深拷貝」
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...
淺拷貝與深拷貝
淺拷貝 1 2 myclass a,b a b 為了封裝性和解耦,同型別的兩個物件之間進行賦值操作時,所有成員變數被複製,包括私有成員 指標變數。類的成員函式在傳遞或返回物件時都會進行物件複製產生臨時物件,比如函式呼叫時實參變為形參,以及函式返回物件。考慮到效能和使用者要求不同,編譯器不複製物件內部...
「淺拷貝」與「深拷貝」
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...