深入探讨 浅拷贝和深拷贝

98 阅读3分钟
含义:
  通常是指将一个引用数据类型, 拷贝到另外一个变量中, 但是根据拷贝的方法不同展示出的效果也有差异
 
 浅拷贝: 将一份数据拷贝到另外一个变量中, 修改第一层数据是不会互相影响, 但是修改第二层数据时会互相影响
 深拷贝: 将一份数据拷贝到另外一个变量中, 不管修改那一层数据, 两个对象之间都不会互相影响

1. 浅拷贝

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

222.jpg

2. 深拷贝

        let obj = {
            name: '张三',
            age: 18,
            info: {
                width: 100,
                height: 280
            }
        }
        let newObj = {}

1)针对面试

    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(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(newObj, obj)
    newObj.age = 99
    newObj.info.width = 999
    console.log('newObj', newObj)
    console.log('obj', obj)
    

111.jpg

    /*
     *  分析:
     *      调用 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}
    */