➀
⑴ JS对象的深拷贝和浅拷贝有什么区别?
◇ 对象B复制对象A,当改变B的时候,A跟着变,那么就是浅拷贝,如果A不变,两者相互不影响,那么就是深拷贝。
⑵ 数据类型:
◇ 值类型(Stack): 包括 Number, String, Boolean, Null, Undefined, Symbol(ES6),
拷贝操作均属于深拷贝,因为它们操作的是实际值。
◇ 引用类型(Heap):包括 Array, Object, Function 等对象,拷贝操作可以是浅拷贝,也可以是深拷贝。
➁
⑴ 值类型拷贝都是深拷贝(number, string, boolean, null, undefined, symbol)。
let a = "hello";
let b = a;
b = "world";
console.log(a);
// hello
⑵ 引用类型 array 浅拷贝
let arrA = [1, 2, 3, 4, 5];
let arrB = arrA;
arrB.push(6);
console.log(arrA);
// [1, 2, 3, 4, 5, 6] A 同时发生了变化
⑶ 引用类型 object 浅拷贝
let objA = { name: "zhangsan", age: 30, course: { chinese: 100 } };
let objB = objA;
objB.name = "lisi";
objB.course.chinese = 89;
console.log(JSON.stringify(objA));
// {"name":"lisi","age":30,"course":{"chinese":89}}
缺点:
会忽略undefined
会忽略symbol
会忽略函数
不能解决循环引用的对象 (会报错)
➂
⑴ 对于单个层级的对象,使用 ES6 语法块 { ... x} 或者 Object.assign() 即可实现深拷贝。
let objA = { name: "zhangsan", age: 30 };
let objB = {...objA};
// let objB = Object.assign({},objA);
objB.name = "lisi";
console.log(objA);
// {name: "zhangsan", age: 30}
使用Object.assign解决这个问题。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
对于嵌套对象,使用这两个方法就“歇菜了”
let objA = { name: "zhangsan", age: 30, course: { chinese: 100 } };
let objB = {...objA}; // 不好用了吧
objB.name = "lisi";
objB.course.chinese = 89;
// {"name":"zhangsan","age":30,"course":{"chinese":89}}
⑵ 嵌套对象,比较“暴力”的深拷贝方法是使用 JSON.parse(JSON.stringify(objA))。
let objA = { name: "zhangsan", age: 30, course: { chinese: 100 } };
let objB = JSON.parse(JSON.stringify(objA));
objB.name = "lisi";
objB.course.chinese = 89;
// {"name":"zhangsan","age":30,"course":{"chinese":100}}
⑶ 手写DeepClone,利用递归的方式实现对象的层层遍历。下面的代码并不完善,例如没有考虑对 date,file,map, set等对象的拷贝。经典库 loadash 提供了 cloneDeep 来实现深拷贝,阅读其源码,发现对10多种常见的对象做了处理,已经较为完善.
◇ 注意判断值类型和引用类型
◇ 注意判断是数组还是对象
◇ 递归
const obj1 = {
age: 20,
name: 'xxx',
address: {
city: 'beijing'
},
arr: ['a', 'b', 'c']
}
const obj2 = deepClone(obj1)
obj2.address.city = 'shanghai'
obj2.arr[0] = 'a1'
console.log(obj1.address.city)
console.log(obj1.arr[0])
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.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
1330

被折叠的 条评论
为什么被折叠?



