// 可以继续遍历的类型
const mapTag = '[object Map]';
const setTag = '[object Set]';
const arrayTag = '[object Array]';
const objectTag = '[object Object]';
const deepTag = [mapTag, setTag, arrayTag, objectTag]
// 不可遍历类型
const boolTag = '[object Boolean]';
const dateTag = '[object Date]';
const errorTag = '[object Error]';
const numberTag = '[object Number]';
const regexpTag = '[object RegExp]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
const funcTag = '[object Function]'
// 使用while替换fon..in
function foreach(arr, iterate) {
let index = -1
let len = arr.length
while (++index < len) {
iterate(arr[index], index)
}
}
// 判断数据类型
function getType(target) {
return Object.prototype.toString.call(target)
}
//初始化数据
function getInit(target) {
const Ctor = target.constructor
return new Ctor()
}
// 判断对象类型
function isObject(target) {
const type = typeof target
return target !== null && (type === 'object' || type === 'function')
}
// 其他类型克隆
function cloneOtherType(target, type) {
const Ctor = target.constructor
switch (type) {
case boolTag:
case errorTag:
case numberTag:
case stringTag:
case dateTag:
return new Ctor(target)
case regexpTag:
return cloneReg(target)
case symbolTag:
return cloneSymbol(target)
case funcTag:
return cloneFunction(target)
default:
return null
}
}
function cloneReg(target) {
const flag = /\w*$/
const result = new target.constructor(target.source, flag.exec(target))
result.lastIndex = target.lastIndex
return result
}
function cloneSymbol(target) {
// return Object(Symbol.prototype.valueOf.call(target));
return Symbol.prototype.valueOf.call(target)
}
function cloneFunction(func) {
const bodyReg = /\{([\s\S]*)\}$/;
// const bodyReg = /(?<={)(.|\n)+(?=})/m;
const paramReg = /(?<=\().+(?=\)\s+{)/;
const funcString = func.toString();
if (func.prototype) {
console.log('普通函数');
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if (body) {
if (param) {
const paramArr = param[0].split(',');
return new Function(...paramArr, body[0]);
} else {
return new Function(body[0]);
}
} else {
return null;
}
} else {
return eval(funcString);
}
}
function deepClone(target, map = new WeakMap()) {
if (!isObject(target)) {
return target
}
const type = getType(target)
let cloneTarget
if (deepTag.includes(type)) {
cloneTarget = getInit(target)
} else {
return cloneOtherType(target, type)
}
if (map.get(target)) {
return target
}
map.set(target, cloneTarget)
// 克隆set
if (type === setTag) {
target.forEach(value => {
cloneTarget.add(deepClone(value));
});
return cloneTarget;
}
// map
if (type === mapTag) {
target.forEach((value, key) => {
cloneTarget.set(key, deepClone(value))
})
return cloneTarget
}
// 对象或数组
for (let key in target) {
cloneTarget[key] = deepClone(target[key], map);
}
return cloneTarget
}
// 测试数据
const map = new Map();
map.set('key', 'value');
map.set('demo', '测试数据');
const set = new Set();
set.add('demo');
set.add('测试数据');
const target = {
field1: 1,
field2: undefined,
field3: {
child: 'child'
},
field4: [2, 4, 8],
empty: null,
map,
set,
bool: new Boolean(true),
num: new Number(2),
str: new String(2),
symbol: Object(Symbol(1)),
date: new Date(),
reg: /\d+/,
// error: new Error(),
func1: () => {
console.log('code秘密花园');
},
func2: function (a, b) {
return a + b;
}
};
console.time('测试');
var clone = deepClone(target)
console.log(clone.func2(1, 2))
// console.log(target)
console.timeEnd('测试');
console