Javascript 对象的浅拷贝和深拷贝
总所周知,在 Javascript 中引用类型的数据赋值给变量时赋的是该对象在栈中的内存地址,而不是堆中的数据,当这个变量 A 再次赋值给另一个变量 B 时,A 和 B 其实共享同一个数据。在很多情况下,我们需要两个独立的相等的对象,因此需要进行 “拷贝
”。
浅拷贝和深拷贝有什么不同?
拷贝的意义是在堆内存中开辟新的区域,用来存一个与原对象值相等的新对象。
深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。
下面开始讲故事了……
// 比如有这么一个人,名字叫 Ann ,年龄 6 岁, 身体健康,心情愉悦
var man = {
name: 'Ann',
age: 6,
state: {
health: 'well',
mood: 'good'
}
}
// 浅拷贝出一个克隆人1
// 克隆人1 改名字叫 Ann Plus ,由于爱吃零食身体变得肥胖
var cloneMan1 = Object.assign({}, man);
cloneMan1.name = 'AnnPlus';
cloneMan1.state.health = 'fat'
// 此时,奇怪的事情发生了,Ann 的身体也变和 AnnPlus 一样肥胖了
console.info(cloneMan1.name, cloneMan1.state.health); // AnnPlus fat
console.info(man.name, man.state.health); // Ann fat
// 又深克隆出一个克隆人2
// 克隆人2 改名字叫 Ann X,由于热爱锻炼身体变得强壮了
var cloneMan2 = JSON.parse(JSON.stringify(man));
cloneMan2.name = 'AnnX';
cloneMan2.state.health = 'strong';
// 此时,Ann 却没有变化
console.info(cloneMan2.name, cloneMan2.state.health); // AnnX strong
console.info(man.name, man.state.health); // Ann fat
// 无论浅克隆或深克隆,改名字 name 都不会影响原对象,但更深一层的身体健康 health 浅克隆仍然与原对象共享同样的内存数据。
分别有哪些实现方式?
浅拷贝的实现方式:
- object.assign({}, obj)
- lodash .clone
- { …obj }
- Array.prototype.concat
- Array.prototype.slice
深拷贝的实现方式
- JSON.parse(JSON.stringify(obj))
- 递归操作
- lodash.cloneDeep
- Jquery.extend()