直接赋值、浅拷贝、深拷贝的区别

赋值

  • 直接赋值的话,不管对象的属性是基本类型的值还是引用类型的值,都会被修改
let obj1 = {
    name: "coderdxh",
    age: 18,
    address: {
        city: "太原",
        school: "中北大学"
    }
}
let obj2 = obj1; // 赋值
obj2.age = 21;
obj2.address.city = "临汾"
console.log(obj1);  
console.log(obj2);
赋值.png

浅拷贝

  • 浅拷贝,被拷贝的对象的基本类型数据不会更改,引用类型数据会被更改
let obj1 = {
    name: "coderdxh",
    age: 18,
    address: {
        city: "太原",
        school: "中北大学"
    }
}

let obj2 = {...obj1};  // 浅拷贝的一种方式 简单版本
obj2.age = 21;
obj2.address.city = "临汾"
console.log(obj1);  
console.log(obj2);
浅拷贝.png
  • 浅拷贝的实现也很简单,就是对要拷贝的对象进行循环,把值赋值给新对象即可
let obj1 = {
    name: "coderdxh",
    age: 18,
    address: {
        city: "太原",
        school: "中北大学"
    }
}

let obj2 = {};
for (let key in obj1) {
    obj2[key] = obj1[key];
}

// 至于为什么基本类型的值没有被改变,引用类型的值被改变:
// 首先obj2它是一个新对象,它有自己的内存地址,跟obj1不是同一个对象
// 那么它的name,age属性赋值的时候,是使用obj1的name,age
// 由于是基本类型的数据,值就在栈内存中,当我们修改obj2的age时,会在栈内存中新开辟一个内存来存放22,再指向22
// 而obj1 age的指向没有发生变化,因此obj1的age不会发生改变
// 而obj2的address赋值的时候,因为是一个引用类型的值,所以赋值是一段内存地址
// 真正的对象数据存放在堆内存中,它们引用同一个数据
// 当我们修改obj2.address.city = "临汾" 时,并没有修改栈内存所保存的内存地址,只是修改了堆内存中对象的数据
// 并没有新创建新的对象,由于obj1同样通过这个内存地址指向这个数据,数据发生更改了,所以obj1.address.city也会发生改变

深拷贝

  • 深拷贝 被拷贝的对象的基本类型数据和引用类型数据都不会被更改
// 深拷贝的简单方式 但是 会忽略 undefined  不能序列化函数  不能解决循环引用的对象
let obj2 = JSON.parse(JSON.stringify(obj1))
let obj1 = {
    name: "coderdxh",
    age: 18,
    address: {
        city: "太原",
        school: "中北大学"
    },
    hobby: ["音乐", "编程", "读书"],
    lovers: undefined,
    show() {}
}
let obj2 = JSON.parse(JSON.stringify(obj1));  // 会忽略 undefined  不能序列化函数  不能解决循环引用的对象
obj2.hobby.push("电影");
console.log(obj2) // {address: {city: "太原", school: "中北大学"},age: 18,hobby: ["音乐", "编程", "读书", "电影"],name: "coderdxh"}
console.log(obj1) // {address: {city: "太原", school: "中北大学"},age: 18,hobby: ["音乐", "编程", "读书"],lovers: undefined,name: "coderdxh",show: ƒ show()}
深拷贝1.png
// 通过函数封装递归实现
function deepClone(obj = {}) {
    if (typeof obj !== "object" || obj == null) {
        // obj 是 null 或者 不是对象 数组 直接返回
        return obj;
    }

    let result;

    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    for (let key in obj) {
        // 保证 key 不是 原型 的属性
        if (obj[key] == undefined) {
            result[key] = undefined
        } else if (obj.hasOwnProperty(key)) {
            // 直接赋值的话,遇到引用类型的值,还是会用之前的地址,所以不可取 
            // result[key] = obj[key]; (这样是浅拷贝)
            // 递归调用
            result[key] = deepClone(obj[key]); // 深拷贝
        }
    }

    return result;
}
let obj1 = {
    name: "coderdxh",
    age: 18,
    address: {
        city: "太原",
        school: "中北大学"
    },
    hobby: ["音乐", "编程", "读书"],
    lovers: undefined,
    show() {}
}

let obj2 = deepClone(obj1);
obj2.age = 22;
obj2.address.city = "临汾";
console.log(obj1);
console.log(obj2);
深拷贝2.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。