深/浅拷贝方法归纳

50 阅读1分钟

浅拷贝

  1. Object.assign
    let obj = {a:1,b:{c:3}}
    let obj1 = Object.assign(obj)
    obj1.b.c = '哈哈'
    console.log(obj, obj1)
    
    image.png
  2. 拓展运算符
    let obj = {a:1,b:{c:3}}
    let obj1 = {...obj}
    obj1.b.c = '哈哈'
    console.log(obj, obj1)
    
  3. concat(只针对数组)
    let arr = [{name:"Livia"},{name:"David"},{name:"Frank"}]
    let arr1 = arr.concat()
    arr1[2].name += "!!"
    console.log(arr, arr1)
    
    image.png
  4. slice(只针对数组)
    let arr = [{name:"Livia"},{name:"David"},{name:"Frank"}]
    let arr1 = arr.slice()
    arr1[2].name += "!!"
    console.log(arr, arr1)
    

深拷贝

  1. JSON.stringify

  2. 第三方库,lodash._cloneDeep()

  3. 简易递归

     function myDeep(obj) {
       let res = {}
       for (let key in obj) {
           if(typeof obj[key] !== 'object' && obj[key] !== null){
               res[key] = obj[key]
           }  else {
             res[key] = myDeep(obj[key])
           }
       }
       return res
     }
     let obj = {
       a: 1,
       b: {
         c: 3,
       }
     }
    
     let obj1 = myDeep(obj)
     obj1.b.c = 666
     console.log(obj, obj1)
    

    image.png

  4. 持续完善版 上述的简易版存在以下问题:

    • 无法正确复制不可枚举属性
      • 使用Reflect.ownKeys解决
    • 只能正确复制基础数据类型,而对于Array、Function等无法正确复制
      • 当遇到Date、RegExp等实例,重新生成对应实例
    • 循环引用问题
      • weakMap作为hash表,可以解决弱引用问题(挖个坑🕳)

    制造难题

    let obj = {
      num: 0,
      str: 'haha',
      bool: true,
      unf: undefined,
      nul: null,
      obj: {
        name:"Frank"
      },
      arr: [5,6,7],
      func: function() {console.log("Hello, Frank")},
      date: new Date(0),
      reg: new RegExp('/正则/ig'),
      [Symbol('1')]: 1,
    }
    
    Object.defineProperty(obj, 'innumerable', {
      enumerable: false,
      value: '不可枚举'
    })
    
    obj.loop = obj
    
    console.log(obj)
    

    image.png

    改良版(有bug,下次再改)

    let obj = {
      num: 0,
      str: 'haha',
      bool: true,
      unf: undefined,
      nul: null,
      obj: {
        name:"Frank"
      },
      arr: [5,6,7],
      func: function() {console.log("Hello, Frank")},
      date: new Date(0),
      reg: new RegExp('/正则/ig'),
      [Symbol('1')]: 1,
    }
    
    Object.defineProperty(obj, 'innumerable', {
      enumerable: false,
      value: '不可枚举'
    })
    
    obj.loop = obj
    
    function deepPlus(obj, map = new WeakMap()) {
      let res = {}
      if(obj instanceof RegExp){
        return new RegExp(obj)
      }
      if(obj instanceof Date){
        return new Date(obj)
      }
      if(map.has(obj)) {
        return map.get(obj)
      }
      let allDesc = Object.getOwnPropertyDescriptors(obj)
      map.set(obj, allDesc)
      for (let key of Reflect.ownKeys(obj)) {
        console.log('key', key, typeof obj[key])
          if(typeof obj[key] === 'object' && obj[key] !== null){
              res[key] = deepPlus(obj[key], map)
          }  else {
            res[key] = obj[key]
          }
      }
      return res
    
    }
    let obj1 = deepPlus(obj)
    console.log("obj", obj)
    console.log("obj1", obj1)