const getType = obj => Object.prototype.toString.call(obj);
const isObject = (target) => (typeof target === 'object' || typeof target === 'function') && target !== null;
const canTraverse = {
'[object Map]': true,
'[object Set]': true,
'[object Array]': true,
'[object Object]': true,
'[object Arguments]': true,
};
const mapTag = '[object Map]';
const setTag = '[object Set]';
const boolTag = '[object Boolean]';
const numberTag = '[object Number]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
const dateTag = '[object Date]';
const errorTag = '[object Error]';
const regexpTag = '[object RegExp]';
const funcTag = '[object Function]';
const handleRegExp = (target) => {
const { source, flags } = target;
return new target.constructor(source, flags);
}
const handleFunc = (func) => {
// 箭头函数间接返回本身
if(!func.prototype) return func;
const bodyReg = /(?<={)(.|n)+(?=})/m;
const paramReg = /(?<=().+(?=)s+{)/;
const funcString = func.toString();
// 别离匹配 函数参数 和 函数体
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if(!body) return null;
if (param) {
const paramArr = param[0].split(',');return new Function(...paramArr, body[0]);
} else {
return new Function(body[0]);
}
}
const handleNotTraverse = (target, tag) => {
const Ctor = target.constructor;
switch(tag) {
case boolTag: return new Object(Boolean.prototype.valueOf.call(target));case numberTag: return new Object(Number.prototype.valueOf.call(target));case stringTag: return new Object(String.prototype.valueOf.call(target));case symbolTag: return new Object(Symbol.prototype.valueOf.call(target));case errorTag: case dateTag: return new Ctor(target);case regexpTag: return handleRegExp(target);case funcTag: return handleFunc(target);default: return new Ctor(target);
}
}
const deepClone = (target, map = new WeakMap()) => {
if(!isObject(target))
return target;
let type = getType(target);
let cloneTarget;
if(!canTraverse[type]) {
// 解决不能遍历的对象return handleNotTraverse(target, type);
}else {
// 这波操作相当要害,能够保障对象的原型不失落!let ctor = target.constructor;cloneTarget = new ctor();
}
if(map.get(target))
return target;
map.set(target, true);
if(type === mapTag) {
//解决Maptarget.forEach((item, key) => { cloneTarget.set(deepClone(key, map), deepClone(item, map));})
}
if(type === setTag) {
//解决Settarget.forEach(item => { cloneTarget.add(deepClone(item, map));})
}
// 解决数组和对象
for (let prop in target) {
if (target.hasOwnProperty(prop)) { cloneTarget[prop] = deepClone(target[prop], map);}
}
return cloneTarget;
}