深浅拷贝

65 阅读3分钟
  • 深浅拷贝
    • 含义: 通常是指将一个引用数据类型,拷贝到另外一个变量中,但是根据拷贝的方法不同,展示出的效果也有差异
    // 赋值
    // let obj = {
    //   name: '张三',
    //   age: 18,
    //   info: {
    //     width: 100,
    //     height: 200
    //   }
    // }
    // let obj2 = obj
    // obj2.age = 20
    // console.log(obj) //20 因为是直接赋值,所以修改obj2会影响obj,所以它内部的name的值也被更改了20

    // 浅拷贝
    // let obj = {
    //   name: '张三',
    //   age: 18,
    //   info: {
    //     width: 100,
    //     height: 200
    //   }
    // }
    // let newObj = {}
    // for(let key in obj) {
    //   console.log(key)
    //   newObj[key] = obj[key]
    // }
    // newObj.age = 99
    // newObj.info.width = 999
    // console.log('newObj', newObj)
    // console.log('obj', obj)

    // 深拷贝
    let obj = {
      name: '张三',
      age: 18,
      info: {
        width: 100,
        height: 200
      }
    }
    let newObj = {}

    // 针对面试
    function deepClone(target, origin) {
      /**
       * target: 目标对象
       * origin: 原始对象
       *    需求: 将原始对象origin 内部的所有属性,拷贝到目标对象target中
       * */ 
      // 1. 通过for...in遍历对象,拿到对象的所有的key与对应的value
      for(let key in origin) {
        // 2. 根据 遍历到的这个属性的属性值是什么类型的,决定执行什么代码
        if(Object.prototype.toString.call(origin[key]) === '[object Object]') {
          // 表明当前这个key的值为一个对象
          target[key] = {}
          // deepClone('目标对象', '原始对象')
          deepClone(target[key],origin[key])
        } else if(Object.prototype.toString.call(origin[key]) === '[object Array]') {
          // 表明当前这个key的值为一个数组
          target[key] = []
          deepClone(target[key], origin[key])
        }else {
          // 表明当前这个key的值一定不是对象或者数组
          target[key] = origin[key]
        }
      }
    }
    /**
     * *  分析:
     * *      调用 deepClone, 第一个参数是一个空对象
     * *          第二个参数内部有三个属性, 分别为 name-age-info, 其中 info 是一个对象
     * *
     * *      函数在执行的时候, 首先会执行一个 for...in 循环遍历 第二个参数
     * *
     * *          for..in 循环第一次执行  key === 'name'  origin[key] === '张三'
     * *              开始运行 循环内部的 分支语句, 因为当前的 value 类型为 string, 所以会走最后一个 else 分支
     * *              那么就是:   target[key] = origin[key]       target.name = '张三'
     * *
     * *          for...in 循环第二次执行 key === 'age'   origin[key] === 18
     * *              开始运行 循环内不的 分支语句, 因为当前的 value 类型为 number, 所以会走最后一个 else 分支
     * *              那么就是: target[key] = origin[key]         target.age = 18
     * *
     * *          两轮循环结束
     * *              此时 origin 这个对象 {name: '张三', age: 18}
     * *
     * *          for...in 循环第三次执行 key === 'info'  origin[key] === {width: 100, height: 280}
     * *              开始运行 循环内不的 分支语句, 因为当前的 value 类型为 Object, 所以会走第一个 分支
     * *              分支内部的代码
     * *                  1. target[key] = {}        {name: '张三', age: 18, info: {}}
     * *
     * *                  2. deepClone(target[key], origin[key])
     * *                          调用 deepClone 第一个参数是一个 空对象
     * *                          第二个参数内部有两个属性, 分别为 width, height
     * *
     * *                          函数在执行的时候, 首先会执行一个 for...in 循环遍历第二个参数
     * *                              for...in 循环第一次执行 key === 'width' origin[key] === 100
     * *                              开始运行 循环内部的 分支语句, 因为当前的 value 类型为 number, 所以会走最后一个 else 分支
     * *                              那么就是: target[key] = origin[key]         target.width = 100
     * *
     * *                              for...in 循环第二次执行 key === 'height' origin[key] === 280
     * *                              开始运行 循环内部的 分支语句, 因为当前的 value 类型为 number, 所以会走最后一个 else 分支
     * *                              那么就是: target[key] = origin[key]         target.height = 280
     * *                  这两轮 for 执行完毕后 target.info === {width: 100, height: 280}
     * */
    deepClone(newObj, obj)
    console.log('newObj', newObj)
    console.log('obj', obj)
    // _.deepClone('目标对象', '原始对象')

    // 针对工作
    newObj = JSON.parse(JSON.stringify(obj))
    console.log('newObj', newObj)
    console.log('obj', obj)