浅拷贝与深拷贝思考
前言
在写这篇文章之前,如果有人问我什么是深拷贝/浅拷贝?如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝。这句话面试回答可以勉强蒙混过关,也是最通俗易懂的一个答案了。但实际开发过程中确总是出现各种“意外事件”。
1、javascript数据类型
内容:
1、了解基本数据类型与引用类型的存储方式
2、拷贝概念只针对引用类型
1.1、基本数据类型
string、number、null、undefined、boolean、symbol(ES6新增) 变量值存放在栈内存中,可直接访问和修改变量的值。
1.2、引用类型
Object Function RegExp Math Date 值为对象,存放在堆内存中。在栈内存中变量保存的是一个指针,指向对应在堆内存中的地址。当访问引用类型的时候,要先从栈中取出该对象的地址指针,然后再从堆内存中取得所需的数据。
2、探究直接赋值、深拷贝、浅拷贝三者之间的关系
内容:
1、赋值
2、深拷贝
3、浅拷贝
2.1、 赋值
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
Let obj1 = {
name:’张三’,age:12}
Let obj2 = obj1
Obj2.name = ‘李四’
Console.log(obj1 ) // {name:’李四’,age:12}
var a = [1,2,3,4];
var b = a; a[0] = 0;
console.log(a,b);
解释:可以看到数组a直接赋值给b,a、b引用的其实是一个对象地址,只要地址值发生变化,a、b栈内存指针指向的堆地址也会发生变化,这种引用拷贝只是新增了一个变量栈内存的指针,意义不大
注意:赋值不需要针对引用类型
2.2、浅拷贝
重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
2.2.1、数组的concat、slice,对象的assign拷贝
1、Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。