深拷贝与浅拷贝的深入理解
变量在内存中的存储
var a = 1
在栈区中 | |
---|---|
a | 1 |
基本数据类型:基本数据类型值指保存在栈内存中的简单数据段,访问方式是按值访问。
a = 2
在栈区中 | |
---|---|
a | 2 |
操作的是变量实际保存的值。
var b = a
在栈区中 | |
---|---|
a | 2 |
b | 2 |
b = 3
在栈区中 | |
---|---|
a | 2 |
b | 3 |
引用类型变量在内存中的存储
引用类型变量的复制:复制的是存储在栈中的指针,将指针复制到栈中未新变量分配的空间中,而这个指针副本和原指针指向存储在堆中的同一个对象;复制操作结束后,两个变量实际上将引用同一个对象。因此,在使用时,改变其中的一个变量的值,将影响另一个变量。
var a = {}
a.name = john
var b = a
b.sex = man
a的值为{name:'john',sex:man}
堆&栈
两者都是存放临时数据的地方。
栈是先进后出的,就像一个桶,后进去的先出来,它下面本来有的东西要等其他出来之后才能出来。
堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。对于堆,我们可以随心所欲的进行增加变量和删除变量,不用遵循次序。
栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
堆区(heap) 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
堆(数据结构):堆可以被看成是一棵树,如:堆排序;
栈(数据结构):一种先进后出的数据结构。
引用类型比如对象储存在堆中
浅拷贝
之前变量在内存中的存储就等于浅拷贝,但是还有一种特殊情况
源对象拷贝实例,其属性对象拷贝引用。
var a = [{c:1}, {d:2}];
var b = a.slice();
console.log(a === b); // 输出false,说明外层数组拷贝的是实例
a[0].c = 3;
console.log(b[0].c); // 输出 3,说明其元素拷贝的是引用
深拷贝
深拷贝后,两个对象,包括其内部的元素互不干扰。常见方法有JSON.parse(),JSON.stringify(),lodash的.cloneDeep和.clone(value, true)