SOURCE

// const cloneTags = {
//     DateTag
// }
const MapTag = '[object Map]';
const SetTag = '[object Set]';

const DateTag = '[object Date]';
const RegExpTag = '[object RegExp]';
const FunctionTag = '[object Function]';

function clone(value, map = new Map()) {
    // 直接拷贝原始类型数据
    if (!clone.__isObject(value)) return value;

    const isArr = Array.isArray(value);
    const tag = clone.__objToStr(value);
    let cloneTarget = new value.constructor();

    if (map.get(value)) {
        return map.get(value);
    }
    map.set(value, cloneTarget);

    // 拷贝 Map
    if (tag === MapTag) {
        value.forEach((v, k) => {
            cloneTarget.set(k, clone(v, map));
        });
        return cloneTarget;
    }

    // 拷贝 Set
    if (tag === SetTag) {
        value.forEach(v => {
            cloneTarget.add(clone(v, map));
        });
        return cloneTarget;
    }

    // 拷贝 Function
    if (tag === FunctionTag) {
        const bodyReg = /(?<=\{)(.|\n)+(?=\})/m;
        const paramReg = /(?<=\()(.)+(?=\)\s*{)/;
        const funcStr = value.toString();

        // 箭头函数无prototype, 判断是否为箭头函数
        if (value.prototype) {
            const body = bodyReg.exec(funcStr);
            const param = paramReg.exec(funcStr);
            if (body) {
                if (param) {
                    const params = param[0].split(',');
                    return new Function(...params, body[0]);
                } else {
                    return new Function(body[0]);
                }
            } else {
                return null;
            }
        } else {
            // 箭头函数通过 eval 生成
            return eval(funcStr);
        }
    }

    // 拷贝 Date
    if (tag === DateTag) {
        return new value.constructor(value);
    }

    // 拷贝数组和对象
    for (const key in value) {
        cloneTarget[key] = clone(value[key], map);
    }
    return cloneTarget;
}

function __objToStr(o) {
    return Object.prototype.toString.call(o);
}
clone.__objToStr = __objToStr;

function __isObject(o) {
    return o !== null && (typeof o === 'object' || typeof o === 'function');
}
clone.__isObject = __isObject;

const myobj = { 
    a: { b: { e: 1 }, c: [1,2,3,4], d: 3 },
    func: function(a,b,c){console.log(123); return {a:1}},
    func0: (a)=>console.log(a),
    date: new Date(191991)
};
myobj.my = myobj;
const newobj = clone(myobj)
console.log(newobj.date === myobj.date);
console 命令行工具 X clear

                    
>
console