如何实现深拷贝?

134 阅读1分钟

满足日常需求的深拷贝函数

背景:使用 JSON.stringify()JSON.parse() 对数据进行拷贝时,存在一定的局限性,对数据类型和数据结构均有一定的要求,因此不能满足日常开发需求

function isBasicType(target) {
    return ["string", "number", "bigint", "symbol", "boolean", "undefined"].includes(typeof target) || target === null;
}

function getType(target) {
    return Object.prototype.toString.call(target).substr(8).replace(/]$/, "");
}

function deepClone(target, _cacheMap) {
    let _type = getType(target);
    if (isBasicType(target)) {
        return target;
    }
    let _result = null;
    _cacheMap = getType(_cacheMap) === "WeakMap" ? _cacheMap : new WeakMap();
    if (_type === "Date") {
        return new Date(target);
    }
    if (_type === "RegExp") {
        return new RegExp(target);
    }
    if (_type === "Function") {
        return target;
    }
    if (_type === "Map" || _type === "WeakMap") {
        _result = _type === "Map" ? new Map() : new WeakMap();
        target.forEach((value, key) => {
            let _val = isBasicType(value) ?
                value :
                (
                    _cacheMap.get(value) ?
                        _cacheMap.get(value) :
                        (_cacheMap.set(value, value), cloneDeep(value, _cacheMap))
                );
            _result.set(key, _val);
        });
        return _result;
    }
    if (_type === "Array") {
        _result = [];
        target.forEach((value, key) => {
            let _val = isBasicType(value) ?
                value :
                (
                    _cacheMap.get(value) ?
                        _cacheMap.get(value) :
                        (_cacheMap.set(value, value), cloneDeep(value, _cacheMap))
                );
            _result[key] = _val;
        });
        return _result;
    }
    if (_type === "Object") {
        _result = {};
        for (let key in target) {
            let value = target[key];
            let _val = isBasicType(value) ?
                value :
                (
                    _cacheMap.get(value) ?
                        _cacheMap.get(value) :
                        (_cacheMap.set(value, value), cloneDeep(value, _cacheMap))
                );
            _result[key] = _val;
        }
        return _result;
    }
    return target;
}