引用类型的深拷贝方法

·  阅读 51

浅拷贝:给新数组或对象直接赋值,结果改变新数组或对象时,直接改变了原数组;其实赋值的只是引用数据类型的引用地址,并不是值;

深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”,新对象跟原对象不共享内存,修改新对象不会改到原对象

为什么要深拷贝?
在工作中,我们经常需要改变新的数组或对象的时候,不改变原数组或对对象;

 //下面的方法都是对这个对象或者是数组进行拷贝
 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
   }
}
复制代码
分类:
前端
收藏成功!
已添加到「」, 点击更改