实现 JavaScript
的深拷贝
// 通过 `Object` 原型对象上的 `toString` 方法,配合正则表达式的分组功能,获取数据的真实类型
// Number BigInt String Boolean Symbol Undefined Null Object Array Promise Function 等等
function getType(data) {
return Object.prototype.toString.call(data).match(/\[object (\w+)\]/)[1];
}
function deepCopy(data) {
const dfs = d => {
const type = getType(d);
if (type === 'Array') {
const tmp = [];
d.forEach(item => {
tmp.push(dfs(item));
});
return tmp;
}
if (type === 'Object') {
// 复制原对象的原型对象
const tmp = Object.create(Object.getPrototypeOf(d));
// getOwnPropertyNames 可以获得当前对象的所有属性,即使 enumerable 为 false
Object.getOwnPropertyNames(d).forEach(key => {
// 获取当前属性的配置
const discriptor = Object.getOwnPropertyDescriptor(d, key);
// 将当前属性配置中的 value 改为深拷贝后的值
discriptor.value = dfs(discriptor.value);
// 在 tmp 中定义配置
Object.defineProperty(tmp, key, discriptor);
});
return tmp;
}
return d;
}
return dfs(data);
}
测试效果:
const data = {
name: 'weixin',
age: [27, 25]
};
data.__proto__.try = function() {};
Object.defineProperty(data, 'age', {enumerable: false, writable: false});
const copiedData = deepCopy(data);
console.log('原对象: ', data);
console.log('新对象: ', copiedData);