js深拷贝与浅拷贝

时间:2022-07-18 19:48:05

实现一个页面或者一个功能时,常常遇到的场景需要我们备份一个数组或者对象,这时候出现了深拷贝与浅拷贝效果截然不同呀总结如下:

浅拷贝:

1 var
2     arr = [1, 2, 3, 4],
3     shallowArr = a;
4 arr[0] = "change";
5 console.log(arr);
6 console.log(shallowArr);

很简单的例子,很明显结果是两个数组第一项同时发生改变,原因是因为arr与shallowArr两数组为同一数组,仅仅是地址名不同,而地址却是同一个。那么如何避免上面的情况发生呢那就是深拷贝了。

深拷贝:

1 var
2     arr = [1, 2, 3, 4],
3     deepArr = [].concat(arr);
4 console.log(arr === shallowArr); // false

上述代码这是针对数组内部为简单类型的深拷贝,当数组内部的成员为引用类型时上面的方式还能算深拷贝吗?

1 var
2     arr = [{ m: 1 }, { n: 2 }],
3     deepArr = [].concat(arr);
4 console.log(arr === deepArr); // false
5 console.log(arr[0] === deepArr[0]); //true

很明显数组地址发生变化,但是数组内的对象地址并未变化,此时这种拷贝方式就是浅拷贝。

最实用的深拷贝实现方式:

1 var
2     arr = [{ m: 1 }, { n: 2 }],
3     deepArr = JSON.parse(JSON.stringify(arr));
4 console.log(arr === deepArr); // false
5 console.log(arr[0] === deepArr[0]);  //false

序列化然后反序列化重新生成一个新的数组(引用对象)。

对象的浅拷贝:

var 
    obj_a = {
        name: "dqhan",
        age: 25,
        sex: "male",
        hobby: {
            1: "eat",
            2: "play"
        }
    },
    obj_b = obj_a;
obj_b.age = 18;

js深拷贝与浅拷贝

 对象的深拷贝:

var 
    obj_a = {
        name: "dqhan",
        age: 25,
        sex: "male",
        hobby: {
            1: "eat",
            2: "play"
        }
    }
function deepFunc(argc) {
    var
        newObj = {};
    for (var property in argc) {
        if (typeof argc[property] == "object") newObj[property] = deepFunc(argc[property]);
        else newObj[property] = argc[property];
    }
    return newObj;
}

 对象与数组均为引用类型,实则原理是一样的。

 总结:

有没有注意,深拷贝对象都是js中引用类型的对象,基本类型的没有涉及,本质上就是引用类型的对象在堆上分配空间,而深拷贝就是重新给对象在堆上分配一个空间,然后将复制内容到这个新的空间中;而浅拷贝恰恰只是在栈上重新定义了一个指针,指向的位置却依然是原来引用对象的堆空间,改变指的时候当然就都变啦~