说明:
记录一下学习过程。对数组和对象进行深度克隆,对于其他类型的数据,则没有进行相应处理。比如:Symbol,Date, RegExp,其实也应该拷贝为一个新的对象返回----通过new的方式。而Function类型,则只需要返回一个新的函数FunA,这个函数FunA里再调用当前函数即可。
实现
/* 能解决循环引用的深度克隆: */
function DeepClone (obj, cach = new Set()) {
const type = Object.prototype.toString.call(obj).slice(8, -1)
if (cach.has(obj)) return obj
cach.add(obj)
if (type === 'Object' || type === 'Array')
{
let Cr = obj.constructor
let newObj = new Cr()
let keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]
for (let i = 0; i < keys.length; i++) {
newObj[keys[i]] = DeepClone(obj[keys[i]], cach);
}
return newObj
} else {
return obj;
}
}
测试
const obj = {
name: 'abc',
age: 19,
[Symbol('symbol')]: function (){console.log(this.name);},
xxx: {
name: 'zhangsan',
age: 18,
}
}
obj.xxx.boyfriend = obj
const newObj = DeepClone(obj)
console.log(obj.name === newObj.name);//true
console.log(obj.age === newObj.age);//true
console.log(obj[Object.getOwnPropertySymbols(obj)[0]] === newObj[Object.getOwnPropertySymbols(newObj)[0]]);//true
console.log(obj.xxx === newObj.xxx);//false <= 表明深度克隆成功
console.log(obj.xxx.boyfriend === newObj.xxx.boyfriend);//true <= 循环引用部分不能被克隆
总结
- 检测数据类型通用的方式:
const type = Object.prototype.toString.call(obj).slice(8, -1)
- 获得对象所有属性,包括Symbol类型:
let keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]