前言
为什么js对象的赋值有时候需要进行深拷贝?
首先js的数据值按照类型主要分为两大类,基本数据类型和引用数据类型。基本数据类型包括Undefined、Null、Number、String、Boolean、Symbol(es6中新增);引用数据类型则为Object,那些Array、function ,es6中新增的map、set也属于Object。
为什么引用数据类型要用深拷贝呢?这个例子就可以很明显告诉你深拷贝和浅拷贝的区别:
let user = {
name: "张三",
age: 18,
}
let user1 = user;
user1.age = 20;
console.log(user1); // name: "张三" age: 20
console.log(user);// name: "张三" age: 20
对于一般的赋值,引用对象的赋值不是将内容复制一份,而是将存放内容的地址复制给了user1,user和user1用的是同一个地址,那必然,改了user1的age ,user的age也会改变。
这就说明了为什么要深拷贝。
一、对象的深拷贝方法
? ? ?1.纯数据对象的深拷贝方法
? ? ? ? ? 1.? ?解构语法
let user = {
name: "张三",
age: 18,
}
// 解构语法
let newuser1 = {...user};
console.log(newuser1)//{ name: '张三', age: 18 }
? ? ? ? ?2.JSON.parse(? ?JSON.stringify()? ?) 序列化和反序列
先将需要拷贝的对象进行JSON字符串化,然后再pase解析出来,赋给另一个变量,实现深拷贝。
let user = {
name: "张三",
age: 18,
};
//先转换为JSON格式在将JSON格式转化成对象
let user1 = JSON.parse(JSON.stringify(user, null, 2));
console.log(user1); //{ name: '张三', age: 18 }
3.利用对象的API,Object.assign()进行深拷贝
let user = {
name: "张三",
age: 18,
};
let newuser2 = Object.assign({}, user);
console.log(newuser2);//{ name: '张三', age: 18 }
4.利用for?in?循环赋值
let user = {
name: "张三",
age: 18,
};
//for in 循环赋值
let newuser3 = {};
for (let key in user) {
newuser3[key] = user[key];
}
console.log(newuser3);//{ name: '张三', age: 18 }
以上的方法,仅仅对仅仅是数据的对象是深拷贝,对于有对象有数组的对象,对于对象里面的数组和对象都浅拷贝,可以通过一些判断和循环可以将对象里面的数组和对象,给深拷贝出来,但是有弊端,就是要知道对象嵌套了多少层。
2.有对象有数组的对象的深拷贝方法
1.递归方法实现深拷贝。
let arrdata = {
name: "lisi",
info: {
age: "18",
height: "188",
},
data: [{
id: "1",
title: "css",
}, ],
};
//递归
function copy2(obj) {
//三目运算符 先判断拷贝目标是对象还是数组,用instanceof判断原型是Array还是Object
let res = obj instanceof Array ? [] : {};
for (const [key, value] of Object.entries(obj)) {
// 对象数组在typeof 中的类型都为object
res[key] = typeof value === "object" ? copy2(value) : value;
}
return res;
}
let newarrdata = copy2(arrdata);
newarrdata.data[0].title = "6666";
console.log(JSON.stringify(newarrdata, null, 2), "拷贝后");
console.log(JSON.stringify(arrdata, null, 2), "拷贝源");
三、总结
浅拷贝:可以理解为一个新的对象只是简单的复制了原有对象的内存地址 新旧对象指向的都是同一个引用地址 深拷贝:完全开辟出的一个新空间来存放和旧对象中一模一样的数据,两者只是内容一样而已, 改变原有对象,新复制出来的对象不会受到任何影响。
|