淺拷貝實(shí)現(xiàn)
1. for···in只循環(huán)第一層
// 只復(fù)制第一層的淺拷貝
function simpleCopy(obj1) {
var obj2 = Array.isArray(obj1) ? [] : {};
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4
2. Object.assign方法
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
3.使用擴(kuò)展運(yùn)算符實(shí)現(xiàn)
對(duì)于引用數(shù)據(jù)類型魂毁,擴(kuò)展運(yùn)算符實(shí)現(xiàn)的是淺拷貝玻佩。
4.用=賦值實(shí)現(xiàn)
let arr1=[0,1,2,3,4],
arr2=arr1;
console.log(arr1===arr2);
arr1[0]=1;
console.log(arr1,arr2);
深拷貝實(shí)現(xiàn)
1.遞歸實(shí)現(xiàn)
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否為對(duì)象,如果是席楚,遞歸復(fù)制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是咬崔,簡(jiǎn)單復(fù)制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
2. JSON.stringify和JSON.parse實(shí)現(xiàn)
var obj1 = {
a: 1,
b: {
c:2
}
}
var obj2 = JSON.stringify(JSON.parse(obj1)),
弊端:
1).如果obj里面有時(shí)間對(duì)象,則JSON.stringify后再JSON.parse的結(jié)果烦秩,時(shí)間將只是字符串的形式垮斯,而不是對(duì)象的形式;
2).如果obj里有RegExp(正則表達(dá)式的縮寫(xiě))、Error對(duì)象只祠,則序列化的結(jié)果將只得到空對(duì)象兜蠕;
3).如果obj里有函數(shù),undefined抛寝,則序列化的結(jié)果會(huì)把函數(shù)或 undefined丟失熊杨;
4).如果obj里有NaN曙旭、Infinity和-Infinity,則序列化的結(jié)果會(huì)變成null
5).JSON.stringify()只能序列化對(duì)象的可枚舉的自有屬性晶府,例如 如果obj中的對(duì)象是有構(gòu)造函數(shù)生成的桂躏, 則使用JSON.parse(JSON.stringify(obj))深拷貝后,會(huì)丟棄對(duì)象的constructor川陆;
6).如果對(duì)象中存在循環(huán)引用的情況也無(wú)法正確實(shí)現(xiàn)深拷貝剂习;
3.通過(guò)jQuery的extend方法實(shí)現(xiàn)深拷貝
var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true為深拷貝,false為淺拷貝
4.lodash函數(shù)庫(kù)實(shí)現(xiàn)深拷貝
let result = _.cloneDeep(test)
5.Reflect法
// 代理法
function deepClone(obj) {
if (!isObject(obj)) {
throw new Error('obj 不是一個(gè)對(duì)象较沪!')
}
let isArray = Array.isArray(obj)
let cloneObj = isArray ? [...obj] : { ...obj }
Reflect.ownKeys(cloneObj).forEach(key => {
cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return cloneObj
}
6.Object.assign 进倍,針對(duì)對(duì)象的value是基本類型
如果對(duì)象的value是基本類型的話,也可以用Object.assign來(lái)實(shí)現(xiàn)深拷貝购对,但是要把它賦值給一個(gè)空對(duì)象
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({}, obj); // obj賦值給一個(gè)空{(diào)}
obj1.a = 3;
console.log(obj.a)猾昆;// 1
7. 用slice實(shí)現(xiàn)對(duì)數(shù)組的深拷貝;用concat實(shí)現(xiàn)對(duì)數(shù)組的深拷貝
8 .使用擴(kuò)展運(yùn)算符實(shí)現(xiàn)(基本數(shù)據(jù)類型的拷貝)
// 當(dāng)value是基本數(shù)據(jù)類型骡苞,比如String垂蜗,Number,Boolean時(shí)解幽,是可以使用拓展運(yùn)算符進(jìn)行深拷貝的
// 當(dāng)value是引用類型的值贴见,比如Object,Array躲株,引用類型進(jìn)行深拷貝也只是拷貝了引用地址片部,所以屬于淺拷貝
var obj= {a: "1", b: "1", c: "2"}
var obj2= { ...obj, a: "5" }
9. 使用var newObj = Object.create(oldObj)
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i]; // 避免相互引用對(duì)象導(dǎo)致死循環(huán),如initalObj.a = initalObj的情況
if(prop === obj) {
continue;
}
if (typeof prop === 'object') {
obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
} else {
obj[i] = prop;
}
}
return obj;
}