深浅拷贝 详解

对象的深浅拷贝

1.浅拷贝的方法

  • =

    • 直接赋值改变其中的一个数组另一个数组也会变

       let arr1=[1,2,3,4]
               let arr2=arr1;
               arr1[0]=9;
               console.log(arr1);//[9, 2, 3, 4]
               console.log(arr2);// [9, 2, 3, 4]

       

  • assign

    • 利用对象的自带方法 Object.assign({},obj)

       let obj = {
                   people:{
                      age:20
                   }
              }
              let p = Object.assign({},obj)
              p.people.age=30;
              console.log(p.people.age);//30
              console.log(obj.people.age);//30

       

       

  • {...arr}

    • es6中的数组解构赋值来拷贝

       

      let arr = [
                      {
                         age:20
                      },{
                          name:'李四'
                      }
                  ]
              let arr1={...arr};
              arr1[1].name="张三"
              console.log(arr[1].name);// 张三
              console.log(arr1[1].name);// 张三

       

       

  • concat

    • 利用数组自带的方法 Array.prototype.concat()

      let arr = [
                      {
                         age:20
                      },{
                          name:'李四'
                      }
                  ]
              let arr1={...arr};
              arr1[1].name="张三"
              console.log(arr[1].name);// 张三
              console.log(arr1[1].name);// 张三

       

       

  • slice

    • 数组的截取方法

      let arr = [
                  1,3,
                      {
                         age:20
                      }
                  ]
              let arr1 = arr.slice() 
              arr1[2].age=30;
              console.log(arr[2].age); //30   
              console.log(arr1[2].age); //30 

       

       

注意:关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

原数组的元素会按照下述规则拷贝:

如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

例如:

  
let arr = [
            1,3,
                {
                   age:20
                }
            ]
        let arr1 = arr.slice() 
        arr1[0]=2;
        console.log(arr[0]);//1
        console.log(arr1[0]);//2

 

2.深拷贝方法

  • JSON.parse(JSON.stringify())

    • 原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

      这种方法虽然可以实现数组或对象深拷贝,但不能处理函数

            
       let arr = [
                      {
                         age:20
                      },{
                          name:'李四'
                      }
                  ]
              let arr1=JSON.parse(JSON.stringify(arr));
              arr1[1].name="张三"
              console.log(arr[1].name);// 李四
              console.log(arr1[1].name);// 张三

       


         

       

  • 手写递归方法

    • 递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

      let arr = [
                  {name:'li'}, 
                  {age:12},
                  ()=>{return 4}
               ]
              let arr1 = deepClone(arr)//调用函数克隆
              console.log(arr1[2]);//()=>{return 4} 可以克隆函数
              console.log(arr === arr1);//false 因为深克隆引用地址不同
              arr1[0].name = "张三"
              console.log(arr[0].name);// li
              console.log(arr1[0].name);// 张三
      // 获取对象的类型
              function getObjType(target) {
                  return Object.prototype.toString.call(target).slice(8, -1)
              }
              // 执行深克隆
              function deepClone(data) {
                  var type = getObjType(data);
                  var obj;
                  if (type === 'Array') {
                      obj = [];
                  } else if (type === 'Object') {
                      obj = {};
                  } else {
                      //不再具有下一层次
                      return data;
                  }
                  if (type === 'Array') {
                      for (var i = 0, len = data.length; i < len; i++) {
                          obj.push(deepClone(data[i]));
                      }
                  } else if (type === 'Object') {
                      for (var key in data) {
                          obj[key] = deepClone(data[key]);
                      }
                  }
                  return obj;
              };

       

       

 

posted @ 2020-11-01 14:11  小不点灬  阅读(279)  评论(0编辑  收藏  举报