浅拷贝
浅拷贝:只复制对象的顶层属性或元素,如果属性或元素是引用类型(如对象、数组等),则拷贝的是它们的引用地址,而不是实际的对象或数组本身的值
影响:如果存在引用类型数据,那么进行浅拷贝后,两个对象中的引用类型数据会指向同一个地址,如果一个发生改变,则另一个也会发生同样的改变。
代码演示
// 原始数据
const bookType = {
name: '童话',
children: [
{name: '格林童话'},
{name: '一千零一夜'}
]
}
// 使用展开语法进行浅拷贝
const newBookType = {...bookType}
console.log("原始数据", bookType);
console.log("新对象" , newBookType);
其中children是引用类型数据,那么我们修改 bookType 或 newBookType 其他一个 chilren,那么两个对象的children都会发生改变
newBookType.children[0].name = "like 童话"
console.log("==========修改children后的两个对象值");
console.log("原始数据", bookType);
console.log("新对象" , newBookType);
深拷贝
深拷贝:递归地复制对象的所有属性或数组的所有元素,包括引用类型数据,这就表示深拷贝得到的对象和原对象都是完全独立的,修改其中一个不会影响另一个
代码演示(如上例子)
深拷贝方式一:JSON.parse(JSON.stringify(拷贝对象)),但是这种深拷贝存在一个局限性和某些问题,比如
- 无法复制函数
- 无法处理循环引用
- 特殊对象类型丢失(Date、RegExp、Map、Set等)
- 性能问题(对于大型对象比较慢)
- 数据精度问题(对大数字或高精度数字会损失精度)
因为这里只是讲解两种拷贝,故不做深研究,针对深拷贝可以写个拷贝函数,处理拷贝中的各种数据类型
// 原始数据
const bookType = {
name: '童话',
children: [
{name: '格林童话'},
{name: '一千零一夜'}
]
}
// 深拷贝
const newBookType = JSON.parse(JSON.stringify(bookType))
console.log("原始数据", bookType);
console.log("新对象" , newBookType);
当修改其中一个,另一个不会受到影响
newBookType.children[0].name = "like 童话"
console.log("==========修改children后的两个对象值");
console.log("原始数据", bookType);
console.log("新对象" , newBookType);
业务场景
- 数据独立性:当你需要两个完全独立的数据副本,保证其中的一个修改不会影响另一个
- 防止修改:希望一个对象为只读,不希望直接修改它,可以深拷贝该对象,在需要时修改深拷贝的对象
- 避免副作用:在某些情况下,函数或方法可能会修改传入参数,但是你不希望输入参数发生改变,则可以深拷贝输入参数,对深拷贝得到的对象进行修改
- 持久化存储:深拷贝可以保证你拷贝对象中的所有属性或数组元素
影响
深拷贝比浅拷贝更消耗资源,因为它需要递归地复制对象的所有属性或数组中的所有元素,因此要注意系统性能