javascript对象浅拷贝 VS 深拷贝

293 阅读2分钟

浅拷贝

定义: 对一个对象进行拷贝时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体

* 其中一个对象的改变都会影响到另一个对象
        var obj1 = { x:1, y:2 }
        var obj2 = obj1;
        obj2.x = 100;
        console.log(obj1, obj2);    //{x: 100, y: 2} {x: 100, y: 2}

深拷贝

定义: 拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝

* 源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响

第一种: for in

        var obj1 = {x: 1, y: 2};
        var obj2 = {};   // 定义一个空对象
        for(var key in obj1) {
              obj2[key] = obj1[key]
        }
        obj2.x = 100;
        console.log(obj1, obj2);    //{x: 1, y: 2} {x: 100, y: 2}

第二种: object.assign()

        var obj1 = { x: 1, y: 2}
        var obj2 = Object.assign({}, obj1);
        obj2.x = 100;
        console.log(obj1, obj2);    //{x: 1, y: 2} {x: 100, y: 2}

第三种: ...运算符

        var obj1 = {x: 1, y: 2}
        var obj2 = {...obj1};
        obj2.x = 100;
        console.log(obj1, obj2);    //{x: 1, y: 2} {x: 100, y: 2}

第四种: JSON.parse(JSON.stringify())

        var obj1 = { x: 1, y: 2}
        var obj2 = JSON.parse(JSON.stringify(obj1));
        ob2.x = 100;
        console.log(obj1, obj2);    //{x: 1, y: 2} {x: 100, y: 2}

除了第四种深拷贝JSON.parse(JSON.stringify()),其他方式只能做一层拷贝。 如果考虑深层的嵌套关系那么就需要用深拷贝了

    怎么实现深拷贝:利用的是递归
    function deepCopy(obj2){
        /*
        * 把一个对象递归拷贝给另外一个对象
        * 源对象与拷贝后的对象没有引用关系,实现克隆
        */
        var obj =  isArray(obj2)?[]:{}; 
        // 判断被拷贝对象是数组还是对象,如果不考虑数组的话,会出现一些问题,
        // 如果被拷贝对象里面有数组对象的话,会把数组变为对象,
        // 如果传进来是一个数组的话,就让它是一个数组的,是一个对象就是一个对象的
        // 取出obj2的所有属性,如果当前拷贝的数据还是一个对象的话,
        // 那么继续调用,deepCopy进行二次拷贝,递归
        for(var property in obj2){
            if(isObject(obj2[property])){
                obj[property] = deepCopy(obj2[property]) 
            }else{
                obj[property] =  obj2[property]
            }
        }
        return obj;
    }
    
    // 判断一个值是不是数组
    function isArray(val){
        return Object.prototype.toString.call(val) === '[object Array]';
        // 这里直接用Es6中的Array.isArray()方法判断是不是数组也是可以的,但是上面那种是一些标准库的常见用法
    }
    // 判断是不是对象
    function isObject(val){
        return typeof val ==='object' && val !== null;
    }
    var obj1 = {x: 1, y: 2, z: { a:3, b: 4}}
    var obj2 = deepCopy(obj1);
    obj2.x = 100;
    obj2.z.a = 200;
    console.log(obj1, obj2);

如有问题请大家指点迷津,谢谢!