本文主要介绍深拷贝和浅拷贝的概念及区别。
咱们先从堆和栈提及。
1、堆和栈
堆和栈都是内存中划分出来用来存储的区域。segmentfault
栈(stack)为自动分配的内存空间,它由系统自动释放;而堆(heap)则是动态分配的内存,大小不定也不会自动释放。
2、数据类型
数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和引用数据类型(Object,Array...)。数组
基本数据类型的特色:直接存储在栈(stack)中的数据
引用数据类型的特色:存储的是该对象在栈中引用,真实的数据存放在堆内存里函数
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中得到实体。spa
3、赋值=浅拷贝??3d
先来讲赋值
对于基本数据类型来讲,赋值无需多说。基本类型的赋值的两个变量是两个独立相互不影响的变量。
可是引用类型的赋值是传址。只是改变指针的指向,例如,也就是说引用类型的赋值是对象保存在栈中的地址的赋值,这样的话两个变量就指向同一个对象,所以二者之间操做互相有影响。指针
var a = { name:'weiwei' }; var b = a; // 新建一个b对象,地址指向a指向的堆 a.name='ww'; console.log(a.name); // 'ww' console.log(b.name); // 'ww' b.age = 22; console.log(b.age);// 22 console.log(a.age);// 22
附上图片说明一张(迷之画风)code
该案例说明了引用类型赋值时传的是地址指向,当一个改变时另外一个也会被改变。对象
再来讲说浅拷贝
浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。blog
let a = { id:1, age: {name:1} } function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } let b=shallowCopy(a); b.id=2;//id为第一层属性,改变浅拷贝后的,原来不会改变 console.log(a.id); //1 b.age.name=2;//name为第二层属性,改变浅拷贝后的,原来会改变 console.log(a.age.name); //2
实现浅拷贝的方法Object.assign()
递归
let a = { age: 1 } let b = Object.assign({}, a); a.age = 2; console.log(b.age); // 1
另外咱们还能够经过展开运算符...
来实现浅拷贝
let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1
浅拷贝只解决了第一层的问题,若是接下去的值中还有对象的话,那么就又回到最开始的话题了,二者享有相同的地址。要解决这个问题,咱们就得使用深拷贝了。
4、深拷贝
1.JSON.parse(JSON.stringify())
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,并且对象会开辟新的栈,实现深拷贝。
这种方法虽然能够实现数组或对象深拷贝,但不能处理函数
2.手写递归方法
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,而后再去复制,就是深度拷贝。
3.函数库lodash
该函数库也有提供_.cloneDeep用来作 Deep Copy
后续将不断更新完善,期待您的批评指正!