一、JS内存空间
在讲浅拷贝和深拷贝之前,我们必须知道不同的数据类型-------简单数据类型和复杂数据类型在空间中是如何存储与传递数据的。
简单数据类型有Number、String、Boolean、Null、Undefined、Symbol等,简单数据类型也叫做值类型。它们是直接存在栈里的,至于什么是栈,这里先记住它的名字,后面再做解释。
复杂数据类型有Function、Array、Object、Math、Date等,复杂数据类型也叫做引用类型。它们的数据是通过栈指向的地址存储在堆里。
上面引出了堆和栈,现在我们来看看不同数据类型到底是如何存储的。
首先看看堆和栈是如何定义的:
栈(stack):栈会自动分配内存空间,会自动释放,存放简单类型,简单的数据段,占据固定大小的空间。
简单(基本/值)类型:String,Number,Boolean,Null,Undefined
堆(heap):动态分配的内存,大小不定也不会自动释放,存放引用类型,指那些可能由多个值构成的对象,保存在堆内存中,包含引用类型的变量,实际上保存的不是变量本身,而是指向该对象的指针-----也可以说是地址。
复杂(引用)类型:Function,Array,Object
简单的来说就是-------简单数据类型是在栈里直接开辟一个空间存放它的值。复杂数据类型则是在栈里开辟一个空间存放它内容的地址(十六进制),这个地址指向存放在堆里的内容。
下面举例说明:
1.简单数据类型存储和传参
var a = 10;
var b = a;
图解如下:
函数里的形参如果是就简单数据类型,它的值也是存储在栈里的
2.复杂数据类型存储和传参
var a = {
name: '小红',
age: 18
}
var b = a;
二、深浅拷贝
拷贝可以理解为赋值。
在一、中提到的两种赋值都是浅拷贝,因为它们只是把存储在栈里的内容进行了赋值。
而所谓的深拷贝就是在复杂数据类型进行赋值时,不会因为一个对象的属性发生改变,另一个对象的属性也随之改变。简单来说,就是复杂数据类型a给另一个复杂数据类型b赋值时,应该跳过栈,直接寻找a在堆里的内容进行拷贝,并在堆里为b开辟新的空间存储地址。
上图就是对复杂数据类型的一个深拷贝,改变对象b的值不会改变a的值,后面再讲解深拷贝如何用代码实现。