深拷贝、浅拷贝

5/10/2023 JS

# 浅拷贝

浅拷贝只拷贝对象的第一层属性,如果属性是引用类型,拷贝的是引用而不是实际的对象。

    let obj1 = {
        a: 1,
        b: { c: 2 }
    }

    // 使用Object.assign进行浅拷贝
    let shallowCopy = Object.assign({}, obj1)

    // 修改shallowCopy中的引用类型属性
    shallowCopy.b.c = 3

    console.log(obj1) // 输出: { a: 1, b: { c: 3 } }
    console.log(shallowCopy) // 输出: { a: 1, b: { c: 3 } }

shallowCopy 和 obj1 的 b 属性指向同一个对象,因此修改 shallowCopy.b.c 也会影响 obj1.b.c。

# 深拷贝

深拷贝会递归地拷贝对象的所有层级,包括嵌套的对象和数组,确保拷贝后的对象和原对象没有任何引用关系。

    // 一个简单的深拷贝函数实现
    function deepClone(obj) {
        if (obj === null) return null
        let clone = Array.isArray(obj) ? [] : {}
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (typeof obj[key] === 'object') {
                    clone[key] = deepClone(obj[key])
                } else {
                    clone[key] = obj[key]
                }
            }
        }
        return clone
    }

    let obj1 = {
        a: 1,
        b: { c: 2 }
    }

    // 使用deepClone进行深拷贝
    let deepCopy = deepClone(obj1)

    // 修改deepCopy中的引用类型属性
    deepCopy.b.c = 3

    console.log(obj1) // 输出: { a: 1, b: { c: 2 } }
    console.log(deepCopy) // 输出: { a: 1, b: { c: 3 } }

deepCopy 和 obj1 完全独立,修改 deepCopy.b.c 不会影响 obj1.b.c。

# 使用现代库或方法

在实际开发中,为了简化深拷贝的过程,通常会使用现成的库或方法,如lodash的_.cloneDeep()或JSON的序列化和反序列化方法:

    let obj1 = {
        a: 1,
        b: { c: 2 }
    };

    // 使用lodash进行深拷贝
    let deepCopy = _.cloneDeep(obj1)

    // 或者使用JSON.parse和JSON.stringify
    let deepCopy = JSON.parse(JSON.stringify(obj1))

    // 然后可以安全地修改deepCopy
    deepCopy.b.c = 3

注意:使用JSON.parse和JSON.stringify方法进行深拷贝有一些局限性,它不能处理函数和循环引用的情况。