深浅拷贝

348 阅读2分钟

拷贝有个大前提,是针对对象的操作,当想复制一个对象的时候,才存在浅拷贝深拷贝之分!!

  1. 浅拷贝的实现方式

    1. Object.assign()

    可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

    1. lodash的clone方法

    2. ...操作符

        let obj1 = { name: 'Kobe', address:{x:100,y:100}}
      
         let obj2= {... obj1}
      
         obj1.address.x = 200;
      
          obj1.name = 'wade'
      
         console.log('obj2',obj2)
      
    3. Array.prototype.concat

      let arr = [1,2,3]; 
      
      let arr2 = [4,5,6];
      
        let arr3 = arr.concat(arr2)
      
      
      
        let arr = [1, 3, {
       username: 'kobe'
       }];
      
       let arr2 = arr.concat();  
      
       arr2[2].username = 'wade';
      
      console.log(arr);
      
    4. Array.prototype.slice

        let arr = [1, 3, {
      
      username: ' kobe'
      
      }];
        let arr3 = arr.slice();
      
        arr3[2].username = 'wade'
      
          console.log(arr);
      
  2. 深拷贝的实现方式

    1. JSON.parse(JSON.stringify())

      可以处理数组和对象的深拷贝,但是不能处理函数和正则,因为这两者基于这两个函数处理后得到的结果不再是正则/函数

      缺点:

      1. 会忽略undefined

        1. 会忽略symbol
        2. 不能序列化函数
        3. 不能解决循环引用的对象
    2. lodash的cloneDeep函数

    3. jQuery.extend函数

    4. 如果所拷贝的对象含有内置对象,但是不包含函数,可以使用messagechannel,可以拷贝undefined和循环引用的对象

        function structuralClone(obj) {
      
         return new Promise(resolve => {
      
      const { port1, port2 } = new MessageChannel()
      
      port2.onmessage = ev => resolve(ev.data)
      
      port1.postMessage(obj)
          })
      
         }
         
         var obj = {
          a: 1,
          b: {
           c: 2
          }
         }
      
        obj.b.d = obj.b
      

      注意该方法是异步的 可以处理 undefined 和循环引用对象

          const test = async () => {
      
          const clone = await structuralClone(obj)
      
      console.log(clone)
      
       }
      
      test()
      
  3. 手写浅拷贝:遍历=>直接等号赋值

浅拷贝

let obj1 = {

  name : '深深地',
arr : [1,[2,3],4],
};

let obj3=shallowClone(obj1)

obj3.name = "春娇";

obj3.arr[1] = [5,6,7] ; 

新旧对象还是共享同一块内存

这是个浅拷贝的方法

function shallowClone(source) {

var target = {};

for(var i in source) {

    if (source.hasOwnProperty(i)) {
    
        target[i] = source[i];
        
    }
    
}

return target;

}

console.log('obj1',obj1) 

console.log('obj3',obj3) 

obj.hasOwnProperty,返回值是一个布尔值,即是否是obj的属性(原型上的是false)

  1. 深拷贝 遍历,如果是简单数据类型直接赋值,如果是复杂数据类型递归。