判断深拷贝还是浅拷贝:修改拷贝之后的数据会不会影响原数据,浅拷贝会影响
// 浅拷贝1:直接赋值
let obj = {
username: "kobe",
age: 39,
sex: { option1: "男", option2: "女" },
};
let obj1 = obj;
console.log(obj1);//...option1: "男"...
obj1.sex.option1 = "233"; // 修改复制的对象会影响原对象
console.log(obj1, obj);//...option1: "233"...
// 浅拷贝2:Object.assign()
// Object.assign(target, source1, source2..) : 将源对象的属性复制 到目标对象上
let obj = {
username: "kobe",
age: 39,
sex: { option1: "男", option2: "女" },
};
let obj2 = {};
Object.assign(obj2, obj);
obj2.age = 18; //深拷贝(不同时改变)
obj2.sex.option1 = "男123"; //浅拷贝(同时改变)
console.log(obj2, obj);
//obj和obj2对应的age不同,option1相同(数组同)
// 浅拷贝3:扩展运算符...
const obj1 = {
name: "peiqi",
info: {
age: 18,
},
};
const obj2 = { ...obj1 };
obj2.name = "kebi"; //深拷贝(不同时改变)
obj2.info.age = 22; //浅拷贝(同时改变)
console.log(obj1, obj2);
// 浅拷贝4: arr.concat(): 数组浅拷贝
let arr = [1, 2, 3, { username: "kobe" }];
let testArr = [4, 5];
let arr2 = [];
arr2 = arr.concat();
arr2[2] = 88888;//深拷贝(不同时改变)
arr2[3].username = "wade";//浅拷贝(同时改变)
// 浅拷贝5:arr.slice(): 数组浅拷贝
let arr = [1, 2, 3, { username: "kobe" }];
let arr3 = arr.slice(0);
arr3[2] = 6;//深拷贝(不同时改变)
arr3[3].username = 'duncan';//浅拷贝(同时改变)
//深拷贝
//JSON.parse(JSON.stringify(arr/obj)) 只能深拷贝js对象/数组
let obj = {username: 'kobe', age: 43};
let obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj2);
obj2.username = 'wade';
console.log(obj2, obj);//wade kobe
//无法深拷贝的点:
//1.拷贝的对象的值中如果有函数/undefined/symbol类型,不会转换,而是丢弃(图1)
function person(name) {
let a= 1;
}
const newObj = JSON.parse(JSON.stringify(person));
//2.无法处理循环引用(即对象的某个属性引用了该对象本身)(图2)
let obj = { username: "kobe", age: 43 };
obj.a = obj;
let obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2, obj); //obj2的uasername:wade,obj2的uasername:Kobe
//3.拷贝Date引用类型会变成字符串,拷贝RegExp,Error引用类型会变成空对象(图1)
let obj = {
a: /abc/,
b: new Error("error"),
c: new Date(),
};
let obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2, obj);
//2.无法拷贝对象的原型链(图4)
function Person(name) {
this.name = name;
}
Person.prototype.say = function () {
alert("Hi!!!");
};
const obj = new Person("Tom");
const newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj, obj);
newObj.say();
图1
图2
图3
图4
自定义实现深拷贝
实现深拷贝
function checkoutType(target){
return Object.prototype.toString.call(target).slice(8,-1);
}
function clone(target){
let result;
let targetType= checkoutType(target)
if( targetType === 'Array'){
result = [];
}else if(targetType === 'Object'){
result = {};
}else{
return target;
}
for(let item in target){
let value = target[item];
if (checkoutType(value) === 'Array'||'Object'){
result[item] = clone(value);
}else{
result[item] = value;
}
}
return result;
}
let obj = {name:'kobe',age:43,hobby:['basketball','football']};
let obj2 =clone(obj);
console.log(obj,obj2);//{name: "kobe", age: 43, hobby: Array(2)} {name: "kobe", age: 43, hobby: Array(2)}
obj2.name = 'wade';
console.log(obj,obj2);//{name: "kobe", age: 43, hobby: Array(2)} {name: "wade", age: 43, hobby: Array(2)}
obj2.hobby[0] = 'paino';
console.log(obj,obj2);//{name: "kobe", age: 43, hobby: Array(2)}hobby: (2) ["basketball", "football"]
// {name: "wade", age: 43, hobby: Array(2)}hobby: (2) ["paino", "football"]
总结
1.浅拷贝:直接赋值
Object.assign()
、扩展运算符
、arr.concat()
、arr.slice()
真正意义上既不是深拷贝,也不是浅拷贝。他只能深拷贝第一层,第二层为浅拷贝
2.深拷贝:
JSON.parse(JSON.stringify(arr/obj))
只能深拷贝js对象/数组,不能拷贝函数、undefined、循环引用、RegExp、Error、Date、对象的原型链上的属性等
参考使用Object.prototype.toString.call
实现自定义深拷贝。