001[Js修炼]手写深拷贝
/**
// 编写一个深度克隆函数,满足以下需求(此题考察面较广,注意细节)
function deepClone(obj) {}
// deepClone 函数测试效果
const objA = {
name: 'jack',
birthday: new Date(),
pattern: /jack/g,
body: document.body,
others: [123, 'coding', new Date(), /abc/gim],
};
const objB = deepClone(objA);
console.log(objA === objB); // 打印 false
console.log(objA, objB); // 对象内容一样
*/
@解法:jayce
function deepClone(obj) {
const cloneObj = {};
if (Object.keys(obj).length > 0) {
for (let i in obj) {
const type = isType(obj[i]);
if (['String', 'Number', 'Boolean', 'Undefined', 'Null'].includes(type)) {
cloneObj[i] = obj[i];
} else if (['RegExp', 'Date', 'Array'].includes(type)) {
const cStruct = Object.getPrototypeOf(obj[i]).constructor;
cloneObj[i] = Reflect.construct(cStruct, [obj[i]]);
} else if (type === 'HTMLBodyElement') {// 这里考虑去换作nodeType === 1 ,这样可以匹配所有元素节点
cloneObj[i] = obj[i].cloneNode();
} else if (type === 'Object') {
cloneObj[i] = deepClone(obj[i]);
} else {
throw new Error(
`${type} is currently not matched!! need add the type!`,
);
}
}
}
function isType(target) {
return Object.prototype.toString.call(target).split(/\W/)[2];
}
return cloneObj;
}
const objB = deepClone(objA);
console.log(objA === objB); // 打印 false
console.log(objA, objB); // 对象内容一样
// TODO:
- 考虑更多解法, 例如使用 call/apply 去替换 反射方法
- 不用构造函数怎么解?
- 类型判断 loadash/ vueUse 中是怎么实现的?去看看