在JS的引用数据类型中会存在这种深拷贝 / 浅拷贝的问题。接下来我就详细的通过代码和堆栈图示的形式来解释这一组概念。
一. 浅拷贝
引用数据类型的变量中保存的是引用地址。变量的引用地址保存在栈区,真正的值保存在堆区。
var a = {name:"zevin",age:"21"};
var b = a;
b.age++;
console.log(a.age); //输出:22
比如上述代码:
- 先定义一个变量——对象
a
,a的引用地址保存在栈区,并且在堆区开辟了一片地址为B001
的内存空间来存储真正的值; - 正常将
a
赋值给b
——由图可见,a
,b
中存储的是同样的引用地址,都指向同一片内存空间; - 变量
b
中的属性值age
自增1; - 输出
a
的属性值age
的值22;
这种引用地址的拷贝就被称为浅拷贝,实际操作的是同一块内存地址。就好比同一套房子又配了一把钥匙一样。
二. 深拷贝【克隆】
var c = JSON.pasre(JSON.stringify(a));
console.log(c); //输出:{name:"zevin",age:"22"}
c.age++;
console.log(a.age); //输出:22
console.log(c.age); //输出:23
对应的深拷贝就是重新声明了一个对象c
,c
的属性值和a
一模一样,即重新开辟了一片地址为B002
的内存空间,在栈区中c
保存的即为B002
引用地址。
上述代码块中改变c的age值,实际操作的是B002中的age值,而B001中的并未改变。
这种值的拷贝就被称为深拷贝,实际是又开辟了一片内存地址。就好比又买了一套相同户型的房子。
三. 拓展
1. 深拷贝的实现方法:
- 对象 --> json字符串 --> 对象:
JSON.pasre(JSON.stringify(a))
; - 调用es6中object对象的assign方法:(把a拷贝到一个空对象中)
Object.assign({},a)
; - lodash第三方库;