浅拷贝
浅拷贝:把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象
如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会变化
常见方法:
- 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象
- 拷贝数组:Array.prototype.concat() 或者 [...arr]
当我们修改原始列表中的嵌套列表的元素时,拷贝后的列表也会受到影响。这是因为浅拷贝只复制了引用,而不是复制对象本身。
// 使用切片操作创建新列表
old_list = [1, 2, [3, 4]]
new_list = old_list[:]
print("Old List:", old_list)
print("New List:", new_list)
// 修改原始列表
old_list[2][0] = 5
// 查看结果,可以发现拷贝后的列表也受到了影响
print("Old List after modification:", old_list)
print("New List after modification:", new_list)
=====================================================
// 输出结果
Old List: [1, 2, [3, 4]]
New List: [1, 2, [3, 4]]
Old List after modification: [1, 2, [5, 4]]
New List after modification: [1, 2, [5, 4]]
浅拷贝注意:
- 如果是基本数据类型拷贝值
- 如果是引用数据类型拷贝的是地址
简单理解:如果是单层对象,没问题,如果有多层就有问题,还是会影响原来对象
深拷贝
深拷贝:拷贝多层,不再拷贝地址
常见方法:
- 通过 JSON 序列化实现
- lodash库 实现
- 通过递归实现
通过递归实现深拷贝
递归:
所谓递归就是一种函数调用自身的操作
- 简单理解:函数内部自己调用自己, 就是递归,这个函数就是递归函数
- 递归函数的作用和循环效果类似
- 由于递归很容易发生“栈溢出”错误(stackoverflow),所以记得添加退出条件 return
// 递归实现深拷贝
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
// 如果不是复杂数据类型则直接返回
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
// 递归调用deepCopy方法进行深拷贝
result[key] = deepCopy(obj[key]);
}
return result;
}
深拷贝思路:
- 深拷贝的核心是利用函数递归
- 封装函数,里面先判断拷贝的是数组还是对象
- 然后开始遍历
- 如果属性值是引用数据类型(比如数组或者对象),则再次递归函数
- 如果属性值是基本数据类型,则直接赋值即可