手写深拷贝

453 阅读1分钟

JSON序列化和反序列化

let a = {
    b: 1,
    c: [1, 2, 3],
    d: { d: '小明', d2: '小红' }
}
let f = JSON.parse(JSON.stringify(a))
f.b = 2
console.log(a.b)//修改了f.b,但a.b并不受影响,说明没有引用
a.c === f.c//输出false,说明复杂类型并未引用同一个地址

缺点:受JSON数据类型的影响,不能支出undefined/函数/date/正则等类型,不支持环状的引用

递归

确定数据类型
循环遍历,简单数据类型返回值,复杂数据类型进行遍历,创建新的对象或函数等,拷贝值进行返回

function deepClone(source) {
    if (source instanceof Object) {
        let dist
        if (source instanceof Array) {
            a = []
        } else if (source instanceof Function) {
            dist = function () {
                return source.apply(this, arguments)
            }
        }
        else {
            dist = {}
        }
        for (let i in source) {
            dist[i] = deepClone(source[i])
        }
        return dist
    }
    return source
}

解决环形引用

需要在每次复制前进行检查,是否已经克隆过了,避免死循环

let cache = []
function deepClone(source) {
    if (source instanceof Object) {
        let cacheDist = findCache(source)
        if (cacheDist) {
            return cacheDist
        } else {
            let dist
            if (source instanceof Array) {
                dist = []
            } else if (source instanceof Function) {
                dist = function () {
                    return source.apply(this, arguments)
                }
            }
            else {
                dist = {}
            }
            cache.push([source, dist])
            for (let i in source) {
                dist[i] = deepClone(source[i])
            }
            return dist
        }
    }
    return source
}

function findCache(source) {
    for (let i = 0; i < cache.length; i++) {
        if (cache[i][0] === source) {
            return cache[i][1]
        }
    }
    return undefined
}