深拷贝
深拷贝指的是将一个对象完整地复制到另一个对象中,即使原始对象中包含了其他对象的引用,也能将其完整地复制过来,使得两个对象在内存中是完全独立的,互不影响。
深拷贝与浅拷贝不同之处在于,浅拷贝只是将原始对象的引用复制给新对象,新对象和原始对象会共享同一个内存空间,对于新对象所做的任何修改都会影响到原始对象。
方法一
const b = JSON.parse(JSON.stringify(a))
此方法有如下缺点:
- 不支持 Date, 正则, undefined,函数等引用类型
- 不支持对象中的循环引用
方法二
思路:
- 使用递归
- 判断类型
- 检查环
- 不拷贝原型上的属性
const deepClone = (a, cache) => {
if (!cache) {
cache = new Map(); // 缓存对象的属性,以保证不会重复拷贝
}
// 如果不是对象则是原始类型直接返回
if (a instanceof Object) {
// 如果缓存中有此属性,则使用缓存的属性,不递归。
if (cache.get(a)) {
return cache.get(a);
}
let result;
if (a instanceof Function) {
// 有 prototype 就是普通函数
if (a.prototype) {
result = function () {
return a.apply(this, args);
};
} else {
result = (...args) => {
return a.call(undefined, ...args);
};
}
} else if (a instanceof Array) {
result = [];
} else if (a instanceof Date) {
// a - 0 可以将日期变成时间戳
result = new Date(a - 0);
} else if (a instanceof RegExp) {
// a.source 是正则表达式的文本
// a.flags 是正则表达式的标志
result = new RegExp(a.source, a.flags);
} else {
result = {};
}
// 缓存
cache.set(a, result);
for (let key in a) {
if (a.hasOwnProperty(key)) {
result[key] = deepClone(a[key], cache);
}
}
return result;
} else {
return a;
}
};