开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第37天,点击查看活动详情
问题分析
查看下面的代码,执行一下:
// 例子1
var name = '张三';
var userName= name;
name = '李四';
console.log(name, userName);
// 例子2
var ary1 = [1, 1, 2];
var ary2 = ary1;
ary1[1] = 3
console.log(ary1, ary2);
// 输出结果:
李四 张三
[ 1, 3, 2 ] [ 1, 3, 2 ]
执行以上代码,得到结果中你糊发现对 name 赋值后修改 name 值后互不影响,但是数组修改后,两个数组的值还是保持一致的。这和对象的存储有关系。在JS 中基础数据类型 string 、number、boolean、null、undefined 赋值是对值的传递。对象是存储在内存中,赋值时是传递的对象的地址,这样如果修改对象属性的值就导致原对象的值也发生改变。
浅拷贝
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝
将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
常见的拷贝有:
- 像基础的赋值 “=” ,赋值的就是对象的引用。
- 使用 Object.assign 对对象复制,但复制的是对象的的引用而不是对象的值本身。
- _.cloneDeep()
- JQuery 中提供 extend 方法
- 使用 JSON.stringify() 方法但是其对 undefined、symbol 和函数 会被忽略,需要谨慎使用。
所以,对于基础数据类型没有深复制和浅复制,而引用类型就会有深复制和浅复制。浅复制和深复制都是对对象的值和引用地址的复制,但是深复制不会对原对象有影响。所以我的理解深复制应该是产生新的引用地址。