美文网首页
关于js的深拷贝

关于js的深拷贝

作者: 凌晨四点打铁匠 | 来源:发表于2022-03-25 16:48 被阅读0次

    今天看到公众号里面一片文章,详细讲解了关于js深拷贝。后面有源代码链接,以下是最终的结果代码:

    const mapTag = '[object Map]';
    const setTag = '[object Set]';
    const arrayTag = '[object Array]';
    const objectTag = '[object Object]';
    const argsTag = '[object Arguments]';
    
    const boolTag = '[object Boolean]';
    const dateTag = '[object Date]';
    const numberTag = '[object Number]';
    const stringTag = '[object String]';
    const symbolTag = '[object Symbol]';
    const errorTag = '[object Error]';
    const regexpTag = '[object RegExp]';
    const funcTag = '[object Function]';
    
    const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];
    
    
    function forEach(array, iteratee) {
        let index = -1;
        const length = array.length;
        while (++index < length) {
            iteratee(array[index], index);
        }
        return array;
    }
    
    function isObject(target) {
        const type = typeof target;
        return target !== null && (type === 'object' || type === 'function');
    }
    
    function getType(target) {
        return Object.prototype.toString.call(target);
    }
    
    function getInit(target) {
        const Ctor = target.constructor;
        return new Ctor();
    }
    
    function cloneSymbol(targe) {
        return Object(Symbol.prototype.valueOf.call(targe));
    }
    
    function cloneReg(targe) {
        const reFlags = /\w*$/;
        const result = new targe.constructor(targe.source, reFlags.exec(targe));
        result.lastIndex = targe.lastIndex;
        return result;
    }
    
    function cloneFunction(func) {
        const bodyReg = /(?<={)(.|\n)+(?=})/m;
        const paramReg = /(?<=\().+(?=\)\s+{)/;
        const funcString = func.toString();
        if (func.prototype) {
            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 cloneOtherType(targe, type) {
        const Ctor = targe.constructor;
        switch (type) {
            case boolTag:
            case numberTag:
            case stringTag:
            case errorTag:
            case dateTag:
                return new Ctor(targe);
            case regexpTag:
                return cloneReg(targe);
            case symbolTag:
                return cloneSymbol(targe);
            case funcTag:
                return cloneFunction(targe);
            default:
                return null;
        }
    }
    
    function clone(target, map = new WeakMap()) {
    
        // 克隆原始类型
        if (!isObject(target)) {
            return target;
        }
    
        // 初始化
        const type = getType(target);
        let cloneTarget;
        if (deepTag.includes(type)) {
            cloneTarget = getInit(target, type);
        } else {
            return cloneOtherType(target, type);
        }
    
        // 防止循环引用
        if (map.get(target)) {
            return map.get(target);
        }
        map.set(target, cloneTarget);
    
        // 克隆set
        if (type === setTag) {
            target.forEach(value => {
                cloneTarget.add(clone(value, map));
            });
            return cloneTarget;
        }
    
        // 克隆map
        if (type === mapTag) {
            target.forEach((value, key) => {
                cloneTarget.set(key, clone(value, map));
            });
            return cloneTarget;
        }
    
        // 克隆对象和数组
        const keys = type === arrayTag ? undefined : Object.keys(target);
        forEach(keys || target, (value, key) => {
            if (keys) {
                key = value;
            }
            cloneTarget[key] = clone(target[key], map);
        });
    
        return cloneTarget;
    }
    

    源码链接:
    github深拷贝地址

    相关文章

      网友评论

          本文标题:关于js的深拷贝

          本文链接:https://www.haomeiwen.com/subject/hjddjrtx.html