深拷贝&浅拷贝

2017-07-19  本文已影响16人  尤樊容

数据保存到对象以后会涉及到拷贝的问题,而数据保存的格式多样,这就涉及到了深拷贝和浅拷贝的问题。
产生的原因:

    var arr1 = [1,2,3,4,5];
    var arr2 = arr1;
    arr2[1] = 6;
    document.write("arr1: " + arr1 + "<br/>");  //打印结果:arr1: 1,6,3,4,5
    document.write("arr2: " + arr2);//打印结果:arr2: 1,6,3,4,5

    //打印结果:
    //arr1: 1,6,3,4,5
    //\arr2: 1,6,3,4,5

用以上方式将数组拷贝到arr2中是直接让两个对象同时指向同一片内存区域,更改其中的一个,另一个也会更改,为了使两个对象保存以后不会互相影响,用下面的一个简单地例子说明:

    var arr1 = [1,2,3,4,5];
    var arr2 = [];
    for(var i = 0; i < arr1.length; i++){
        arr2[i] = arr1[i];
    }
    arr2[1] = 6;
    document.write("arr1: " + arr1 + "<br/>");
    document.write("arr2: " + arr2);
    
    //打印结果:
    //arr1: 1,2,3,4,5
    //arr2: 1,6,3,4,5

使用循环将arr1里面的数据一一添加到新的对象中,这样打印出来的结果就不会相互影响,也就是一个浅拷贝。
Array的slice函数也可以实现浅拷贝:

    //此方法只针对Array
    var arr1 = [1,2,3,4,5];
    var arr2 = arr1.slice(1);
    arr2[0] = "a";
    document.write(arr1 + "<br/>");
    document.write(arr2);

    //输出结果:
    //1,2,3,4,5
    //a,3,4,5

但是这个方法也只是浅拷贝的一种,数组有多层的时候也是不行的,例如:

    var arr1 = [[1,11],[2,22],[3,33]];
    var arr2 = arr1.slice(1);
    arr2[0][1] = "a";
    document.write(arr1 + "<br/>");
    document.write(arr2);

    //输出结果:
    //1,11,2,a,3,33
    //2,a,3,33

Array的concat函数也是浅拷贝,实例如下:

    var arr1 = [1,2,3];
    var arr2 = [4,5,6];
    var arr3 = arr1.concat(arr2);
    arr2[1] = "aa";
    document.write(arr3);

    //输出结果:
    //1,2,3,4,5,6

生成的第三个数组是独立的,受arr1和arr2影响。但也只能实现浅拷贝。

浅拷贝只是拷贝了对象最外面的一层,但是并不是所有的对象都是简单到只有一层,所以出现了深拷贝,利用递归将对象深拷贝。
用递归写了一个例子:

var object1 = [1,2,3,4,{a:"aaa", b:"bbb"},6,7,[8,9,{c:"ccc", d:"ddd"}]];
function deepCopy(obj, newObj) {
    var newObj = newObj || ((obj.constructor === Array) ? [] : {});
    for (var i in obj) {
        if (typeof obj[i] === 'object') {
            newObj[i] = (obj[i].constructor === Array) ? [] : {};
            deepCopy(obj[i], newObj[i]);
        } else {
            newObj[i] = obj[i];
        }
    }
    return newObj;
}
var arr = deepCopy(object1);
arr[4].a = "ccc";
console.log(object1);// [1,2,3,4,{a:"aaa", b:"bbb"},6,7,[8,9,{c:"ccc", d:"ddd"}]]
console.log(arr);// [1,2,3,4,{a:"ccc", b:"bbb"},6,7,[8,9,{c:"ccc", d:"ddd"}]]

在拷贝的时候检查数据的格式,然后分情况拷贝。这样的方法可以提高代码的重用,在数据格式未知的情况下,避免出错,但是这样写在某些情况下也会降低代码执行的效率,比如数据已知并且单一的情况下,浅拷贝就可以满足,并且可以提高代码执行的效率。

上一篇 下一篇

猜你喜欢

热点阅读