浅拷贝:
正常复制一个对象,它们都是指向同一个内存地址,改变一个对象的属性另外一个也会跟着改变
我们新创建一个新的空对象,再把另外一个对象里的内容复制过来,这样它们就不会有关联了
1.什么是浅拷贝?
把数组/对象第一层的值, 复制到新的数组/对象中
2.浅拷贝使用场景?
修改数组/对象, 影响另一个数组/对象, “砍断”它们的联系
3.如何实现浅拷贝?
for/for...in/扩展运算符/Object.assign()对象用
深拷贝:
如果一个对象里的值有多层的时候,这是浅拷贝只能拷贝第一层的值,第二层的值相互引用
什么是深拷贝?
把数组/对象所有层的值, 复制到新的数组/对象中
如何实现深拷贝?
- 创建新数组/对象
- 判断基础类型, 直接赋值
- 判断对象类型, 递归调用函数, 继续创建判断
- 函数最终返回新数组/对象
let oldObj = {
name: "小明",
age: 18,
grade: [100, 90],
family: {
fName: "王"
}
}
// 实现: 深拷贝
// 注意: 先写Array类型的判断(因为Array的父类是Object, 写在上面无论数组对象都会进去)
let newObj = {};
function deepClone(newO, old){
for (let key in old) {
let value = old[key]
if (value instanceof Array) {
newO[key] = [] // 被拷贝的是数组, 创建一个新数组
deepClone(newO[key], value)
} else if (value instanceof Object) {
newO[key] = {} // 新对象
deepClone(newO[key], value)
} else {
newO[key] = value; // 基础类型, 单纯值复制
}
}
}
deepClone(newObj, oldObj);
oldObj.grade.push(600);
console.log(newObj);
// 总结: 深拷贝
// 递归每层引用类型, 遇到对象/数组, 创建一个新的, 把基础值复制过来
深拷贝_循环引用问题解决
let oneObj = {
name: 'oneObj'
}
let twoObj = {
name: "twoObj",
age: 18,
grade: [100, 90],
family: oneObj // two引用one
}
// one引用two(造成循环引用-互相引用)
oneObj.a = twoObj
// 方案: ES6: Map集合结构
// Map对象key可以是任意类型(对象类型)
let newObj = {};
function deepClone(newO, twoObj, map){ // {}, twoObj对象, oneObj对象
if (!map) {
map = new Map()
}
for (let key in twoObj) { // key: 'family'
let value = twoObj[key] // value: oneObj对象, 读到a的时候, twoObj又进来了
if (value instanceof Array) {
newO[key] = []
deepClone(newO[key], value)
} else if (value instanceof Object) {
newO[key] = {}
if (!map.has(value)) { // 如果这个对象在map里出现过, 就不要再进入递归拷贝了(防止无限递归)
map.set(value, 1) // map值: Map{ objObj对象: 1, twoObj对象: 1 }
deepClone(newO[key], value, map)
}
} else {
newO[key] = value;
}
}
}
deepClone(newObj, twoObj);
console.log(newObj);
// 总结:
// 在递归的时候, 判断map集合中, 是否出现过这个值的对象
// 没有出现过, 递归进入
// 出现过了, 就留下一个空数组/空对象