js深浅拷贝

作者: 王希桐 | 来源:发表于2020-04-12 17:14 被阅读0次

    对象类型在赋值的过程中其实是复制了地址,这样会导致一方改变的时候其他地方也都会被改变的情况

    例:

    let a = {
        age: 1
    }
    let b = a;
    a.age = 2;
    console.log(b.age); //  2
    

    这种情况下我们就可以使用浅拷贝来解决这个问题

    浅拷贝

    浅拷贝只是拷贝基本类型的数据,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,因此存在父对象被篡改的可能,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存

    1、Object.assign

    这个属性并不是用来实现深拷贝的,相反可以用来实现浅拷贝。Object.assign只会拷贝所有的属性到新的对象中,如果属性值是对象的活,拷贝的就是地址,所以不是深拷贝

    例:

    let a = {
        age: 1
    };
    let b = Object.assign({}, a);
    a.age = 2;
    console.log(b.age); //  1
    

    2、展开运算符 ...

    let a = {
        age: 1
    };
    let b = {...a};
    a.age = 2;
    console.log(b.age); //  1
    

    但是浅拷贝只能解决第一层的问题,如果对象下边的值还有对象的话,那么还是会有问题,如果想继续解决就要使用深拷贝了。

    问题实例:

    let a = {
      age: 1,
      jobs: {
        first: 'FE'
      }
    }
    let b = { ...a }
    a.jobs.first = 'native'
    console.log(b.jobs.first) // native
    

    深拷贝

    深拷贝就是能够实现真正意义上的数组和对象的拷贝。递归调用"浅拷贝"。(深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象)

    通常可以通过

    JSON.parse(JSON.stringify(object));
    

    解决

    let a = {
      age: 1,
      jobs: {
        first: 'FE'
      }
    }
    let b = JSON.parse(JSON.stringify(a))
    a.jobs.first = 'native'
    console.log(b.jobs.first) // FE
    

    但是这种方法也有局限性

    • 会忽略undefined
    • 会忽略symbol
    • 不能序列化函数
    • 不能解决循环引用的对象

    例如

    let obj = {
      a: 1,
      b: {
        c: 2,
        d: 3,
      },
    }
    obj.c = obj.b
    obj.e = obj.a
    obj.b.c = obj.c
    obj.b.d = obj.b
    obj.b.e = obj.b.c
    let newObj = JSON.parse(JSON.stringify(obj))
    console.log(newObj)
    

    js实现深拷贝具体方法

    // 深拷贝
    function deepClone(obj, hash = new WeakMap()) {
        if (obj == null) {
            return obj;
        }
        if (obj instanceof Date) {
            return new Date(obj);
        }
        if (obj instanceof RegExp) {
            return new RegExp(obj);
        }
        if (typeof obj !== 'object') {
            return obj;
        }
    
        if (hash.has(obj)) {
            return hash.get(obj);
        }
        let cloneObj = new obj.constructor;
        hash.set(obj, cloneObj);
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                cloneObj[key] = deepClone(obj[key], hash);
            }
        }
        return cloneObj;
    }
    

    本篇文章只是自己对深浅拷贝的一个简单理解,也参考了一些其他文章

    参考文献:
    https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bed40d951882545f73004f6

    https://www.cnblogs.com/136asdxxl/p/8645750.html

    相关文章

      网友评论

        本文标题:js深浅拷贝

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