赋值
- 直接赋值的话,不管对象的属性是基本类型的值还是引用类型的值,都会被修改
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