浅拷贝与深拷贝

谈到深拷贝与浅拷贝,首先我们需要先说一下数据类型。

数据类型分为基本数据类型和引用数据类型。

基本数据类型包括(String,Number,Boolean,Null,Undefined,Symbol),它们的特点是:直接存储在栈中。

引用数据类型包括(Object,Array,Function),它们的特点是:在栈中存储的是该对象在栈中的引用,真实的数据存放在堆内存里。

 

 

浅拷贝与深拷贝

下面说一下深拷贝和浅拷贝的概念:

浅拷贝:浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

深拷贝:深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

下面举例来展示赋值、浅拷贝、深拷贝它们的区别:

1.赋值对象:

let obj1 = {
    name : '张三',
    arr : [1,[2,3],4],
};
let obj2 = obj1;
obj2.name = "李四";
obj2.arr[1] =[5,6,7] ;
console.log('obj1',obj1)
console.log('obj2',obj2)

浅拷贝与深拷贝

根据结果我们可以看到,对象obj1的值也发生了变化,原因是当我们把一个对象赋值给一个新的变量时,赋的是该对象在栈中的地址,而不是堆中的数据。因此,两个对象是联动的,改变一个,另一个也会跟着改变。

2.浅拷贝:

let obj1 = {
    name : '张三',
    arr : [1,[2,3],4],
};
function scopy(aa){
    var dst={}
    for(var prop in aa){
        if(aa.hasOwnProperty(prop)){
            dst[prop]=aa[prop];
        }
    }
    return dst;
}
let obj3=scopy(obj1);
obj3.name = "李四";
obj3.arr[1] =[5,6,7] ;
console.log('obj1',obj1)
console.log('obj3',obj3)

浅拷贝与深拷贝

根据结果我们可以看到,obj1的名字没有被改变,但是数组却被改变了,这是因为浅拷贝时如果属性是基本数据类型,拷贝的就是基本数据类型的值,如果拷贝的是引用对象类型,拷贝的就是内存地址,因此对象obj1的数组发生了改变。

3.深拷贝:

let obj1 = {
    name : '张三',
    arr : [1,[2,3],4],
};
let obj4 = JSON.parse(JSON.stringify(obj1));
obj4.name = "李四";
obj4.arr[1] =[5,6,7] ;
console.log('obj1',obj1)
console.log('obj4',obj4)

浅拷贝与深拷贝

由结果可以看出,但我们执行深拷贝的时候,会创造另外一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原来的对象。ps:JSON.parse(JSON.stringify())是通过转化为序列化与反序列化来还原js对象实现的深拷贝。