浅拷贝和深拷贝

295 阅读3分钟

本文主要介绍浅拷贝和深拷贝

数据类型

1.浅拷贝和深拷贝是针对引用类型,比如Array,Object,基本类型的值存储在栈中,当复制时,栈内存会开辟一个栈内存,所以两者不会受影响

2.引用数据类型:存储的是该对象在栈中的引用,真实的数据存放在堆内存中

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解析器寻找引用纸时,会首先检索其在栈中的地址,取得地址后从堆中获取实体。

指针的概念: 指针存储某一个值得引用而非值本身。


关于栈内存和堆内存

形象化的理解

Object obj = new Object();   

以上这句话,会把obj这个引用放进栈内存,再说白一点,就是这个对象的名字obj放进栈内存,栈内存运行速度较快,用于查找索引(也就是名字)   

而new Object()会在堆内存中开辟一块空间给这个对象,对象几乎所有的属性啊,方法啊,全都在里面了,也就是对象的实体都在堆内存中,堆内存速度慢但是成本低,空间较大,用以存放程序  

浅拷贝(Shallow Copy)

只复制指向某个对象的指针,而不是复制对象的本身,新旧对象还是共享同一块内存。 

比如


上图 SourceObject是原始对象,有基本类型name1和list引用类型。浅拷贝之后name1和name2是不同属性,互不影响。list是同一个对象,改变之后会影响另一个对象

list复制指向对象的指针,不是复制对象的本身

比如Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

var obj = { a: {a: "cong", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "zhou";
console.log(obj.a.a); //zhou 

当object只有一层的时候,是深拷贝

let obj = {
    username: 'zhou'
    };
let obj2 = Object.assign({},obj);
obj2.username = 'cong';
console.log(obj);//{username: "zhou"} 

深拷贝(Deep Copy)

它会创造出一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象

深拷贝相较于浅拷贝速度慢并且花销更大。深拷贝的两个对象互不影响。

比如JSON.parse(JSON.stringify(object))

var a = {
    name: 'zhou',
    book: {
        name: 'Vue.js',
        price: 50
    }
};
var b = JSON.parse(JSON.stringify(a));
b.name = 'hahaha';
b.book.price = 52;
console.log(a); // { name: 'zhou', book: { name: 'Vue.js', price: 50 } }
console.log(b); // { name: 'hahaha', book: { name: 'Vue.js', price: 52 } }

原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

深拷贝与浅拷贝的主要区别在于 

对象中的子对象 改变的时候原数据子对象的值会不会改变

1.浅拷贝会改变

2.深拷贝不会改变

看完这篇文章有没有对深拷贝浅拷贝深入的了解呢?