写一个我心目中的完美深拷贝
要求:
1. 实现传入参数的深拷贝,并返回拷贝后的对象。
2. 要考虑到日期、正则等特殊类型,还有ES6的新数据类型。
3. 要考虑循环引用情况。
思路:
基础数据类型的深拷贝,只要考虑一下是对象还是数组,递归即可。完美深拷贝难点在循环引用和特殊类型。
循环引用可以用一个Map解决。
特殊类型,万变逃不开它的构造函数,只要用构造函数初始化一个新对象,保证原型都是一样一样的。
特殊类型也可能有自定义属性,记得创建完跟普通类型一起扔进循环里递归。
还有es6新数据类型symbol,不能被普通枚举,要用自己的特殊方法getOwnPropertySymbols()。
代码:
const deepCopy = (target, map=new Map()) => {
// 基础类型直接返回
if (typeof target !== 'object' || target === null) return target;
// 查询循环引用
if (map.has(target)) return map.get(target);
// 创建待返回对象, 并保持原型一致
const res = new target.constructor(target);
// 存map
map.set(target, res);
// 遍历属性并拷贝
const keys = Object.getOwnPropertyNames(target);
const symbols = Object.getOwnPropertySymbols(target);
[...keys, ...symbols].forEach(item => {
res[item] = deepCopy(target[item]);
})
return res;
}
// 测试
const o1 = {
name: 'o',
o: {
name: o1.name,
},
d: new Date(),
q: [1,2],
a: '11',
f: function() {},
r: /\d+/
}
o1.d.aaa = 1;
console.log(o1);
const o2 = deepCopy(o1);
console.log(o2);