/**
// 編寫一個深度克隆函數,滿足以下需求(此題考察面較廣,注意細節)
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 中是怎麼實現的?去看看