浅拷贝:给新数组或对象直接赋值,结果改变新数组或对象时,直接改变了原数组;其实赋值的只是引用数据类型的引用地址,并不是值;
深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”,新对象跟原对象不共享内存,修改新对象不会改到原对象
为什么要深拷贝?
在工作中,我们经常需要改变新的数组或对象的时候,不改变原数组或对对象;
//下面的方法都是对这个对象或者是数组进行拷贝
let obj={
a:'22',
b:undefined,
arr:[1,2,3],
c:()=>{},
d:{
e:20
}
} //初始化一个对象
let arr1 = [1,2,3,4,undefined,{c:undefined,fn:()=>{}}] //初始化一个数组;
复制代码
- JSON转换方式;
先把对象转换成字符串,然后再把字符串转换为对象;
缺点:数据为function或者是undefined无法拷贝;
如果数据种没有function或者不需要undefined值的可以用此方法;
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.a = '333'
obj2.arr = [4,5,6]
//结果obj不变; obj2 为{
a:'333',
arr:[4,5,6],
d:{
e:20
}
}
复制代码
- 扩展运算符和 Object.assign方法
缺点:只能拷贝一级属性,二级以上(引用数据类型)属性就是浅拷贝;
没有二级以上引用数据类型可以用此方法
let obj3 =Object.assign({},obj);
let obj4 = {...obj}
obj3.a = '333'
obj3.arr = [4,5,6]
obj3.d.e = 50;
//结果obj和obj4
{
a:'22',
b:undefined,
arr:[1,2,3],
c:()=>{},
d:{
e:50
}
}
//结果obj2
{
b:undefined,
a:'333',
arr:[4,5,6],
c:()=>{
},
d:{
e:50
}
}
复制代码
- 如果是数组,还有slice和concat方法,还有新建一个数组循环遍历push到这个数组种;
缺点:和扩展运算符与Object.assign方法一样,只能拷贝一级属性,二级以上(引用数据类型)属性就是浅拷贝;
//slice方法
let arr2 = arr1.slice();
//contact方法
let arr2 = arr1.concat();
arr2[0] = 5
arr2[5].c = 6
console.log(arr1,arr2)
//结果 arr1
[1,2,3,4,undefined,{c:6,fn:()=>{}}]
//结果 arr2
[5,2,3,4,undefined,{c:6,fn:()=>{}}]
//循环遍历push方法
function copy(arr){
let newArr= [];
arr.forEach(item=>{
newArr.push(item);
})
return newArr;
}
let arr1 = [1,2,3,4,undefined,{c:undefined,fn:()=>{}}]
let copyArr = copy(arr1);
copyArr[0] = 3
copyArr[5].c = 10;
console.log(arr1,copyArr);
//结果 arr1
[1,2,3,4,undefined,{c:10,fn:()=>{}}]
//结果 arr2
[3,2,3,4,undefined,{c:10,fn:()=>{}}]
复制代码
- 递归方法(这个方法是比较完美的解决方式)
function deepClone(obj){
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = deepClone(obj[key]); //递归调用
} else {
result[key] = obj[key];
}
}
}
return result;
}
let arr3 = deepClone(arr1);
arr3[0] = 5
arr3[5].c = 6
console.log(arr1,arr3);
//结果 arr1不变 arr3
[5,2,3,4,undefined,{c:6,fn:()=>{}}]
let obj5 = deepClone(obj);
obj5.d.e = 50;
console.log(obj,obj5);
//结果 obj不变 obj5
{
b:undefined,
a:'333',
arr:[1,2,3],
c:()=>{
},
d:{
e:50
}
}
复制代码