浅拷贝与深拷贝

2021-12-29 15:50阅读 74

JavaScript中数据类型分为基本类型和复杂类型(引用类型)

基本类型:String,Number,Boolean,undefined,null,Symbol, BigInt

复杂类型:object(包含 Array、Object、Date、RegExp等)

const clone = JSON.parse(JSON.stringify(json))

转为JSON字符串再解析为JSON对象,只能处理基本类型,丢失 function、Symbol、Date 等特殊对象。

function deepCopy(data) {
    if (!data) return data
    if (typeof(data) !== 'object') return data
    const cloneTarget = Array.isArray(data) ? [] : {}
    for (const key in data) {
        cloneTarget[key] = data[key]
    }
    return cloneTarget
}

当象内部存在循环引用会导致深拷贝无限循环,最终导致堆栈溢出,可以用map记录已拷贝的对象,避免重复拷贝

function deepCopy(data, cache = new WeakMap()) {
    if (!data) return data
    if (typeof(data) !== 'object') return data
    if (cache.has(data)) return data
    const cloneTarget = Array.isArray(data) ? [] : {}
    cache.set(data, cloneTarget)
    for (const key in data) {
        cloneTarget[key] = deepClone(data[key], cache)
    }
    return cloneTarget
}

单独处理Date、RegExp、Map、Set

function deepCopy(data, cache = new WeakMap()) {
    if (!data) return data
    if (typeof(data) !== 'object') return data
    if (data instanceof Date) return new Date(data)
    if (data instanceof RegExp) return new RegExp(data)
    if (typeof obj === 'function') {
        return obj.bind(null);
    }
    if (obj instanceof Node) {
        return obj.cloneNode(true);
    }
    if (data instanceof Map) {
        const map = new Map();
        data.forEach((value, key) => map.set(key, deepClone(value, cache)));
        return map;
    }
    if (data instanceof Set) {
        const set = new Set();
        data.forEach(value => set.add(deepClone(value, cache)));
        return set;
    }
    if (cache.has(data)) return data
    const cloneTarget = Array.isArray(data) ? [] : {}
    cache.set(data, cloneTarget)
    for (const key in data) {
        cloneTarget[key] = deepClone(data[key], cache)
    }
    return cloneTarget
}
标签
标签
标签