一、认识堆结构
先从一条面试题开始:说说var const let的区别,相信这个问题大家都能说很多;下一个问题:const定义的值能修改吗?这个很多该说不能。
但是呢:正确答案是部分能,部分不能。
解析:const定义的基本变量类型是不能修改的,但是定义的对象是可以通过修改对象属性等方法进行修改。
因此当我们定义一个const对象的时候,我们说的常量其实是指针,就是const对象对应的堆内存指向是不变的,但是堆内存中的数据本身的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就相当于const对象的指针,是不可变。
const obj = {name: 'zhangsan',age: 18}const conNum = 1// 如果直接修改conNum的值就会报错conNum = 2 // 报错// 但是如果修改obj里面的值,就可以修改obj.name = 'lisi'console.log(obj.name) // lisi
- 堆是一种经过排序的树形数据结构,每个结点都有一个值。(是一种树状结构)
- 堆的存取是随意,这就如同我们在图书馆的书架上取书。
好比在JSON格式的数据中,我们存储的key-value是可以无序的,只要知道key,就能取出这个key对应的value。
二、栈内存和堆内存的示意图

栈内存中的变量一般都是已知大小或者是有范围上限的,算是一种简单的存储。这也是会出现栈溢出的原因之一。
堆内存中存储的对象类型数据大小方面一般都是未知的,也就是可以存比较大的数据。三、内存分配和垃圾回收
一般来说栈内存线性有序存储,容量小,系统分配效率高。
- 而堆内存首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些了。
- 垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收。
四、JavaScript中的基本类型和引用类型与堆栈的关系
1、基本类型
Undefined Null Boolean Number String五种基本数据类型在内存中分别占有固定大小的空间,他们的值保存在栈空间(内存)中,按值访问,因此可以操作保存在变量中的实际的值2、引用类型
引用类型的值保存在堆内存中,值大小不固定,栈内存中存放地址指向堆内存中的对象按引用访问。
栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。 这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。
五、复制变量(深浅拷贝)
1、基本类型的拷贝
```javascript var a = 20; var b = a; b = 30;
// 这时a的值是多少? 20
**在变量对象中的数据发生复制行为时,系统会自动为新的变量分配一个新值,最后这些变量都是相互独立互不影响的**。var b = a执行之后,a与b虽然值都等于20,但是他们其实已经是相互独立互不影响的值了。由于基本类型是按值访问的,所以我们修改了b的值以后,a的值并不会发生变化。<br /><a name="DjRAn"></a>## 2、引用类型的拷贝基本类型拷贝的时候只是在内存中又开辟了新的空间,和它被拷贝的对象属于 互不想干的东西,因此深浅拷贝是相对于引用类型的。```javascriptvar m = { a: 10, b: 20 }var n = m;n.a = 15;// 这时m.a的值是多少 15
- 引用类型的复制,同样为新的变量n分配一个新的值,保存在栈内存中,不同的是,这个值仅仅是引用类型的一个地址指针;
- 他们两个指向同一个值,也就是地址指针相同,在堆内存中访问到的具体对象实际上是同一个;
- 因此改变n.a时,m.a也发生了变化,这就是引用类型的特性。

- 浅拷贝:当我们改变子对象(复制出来的新对象)时,父对象(被拷贝的对象)也会跟着改变的拷贝。也就是说,子对象和父对象在浅拷贝的时候他们指向同一个内存的对象。
- 深拷贝:就是把父对象拷贝到子对象上,而且两者的内存和以后的操作都互不影响的拷贝!
3、深拷贝和浅拷贝的区别
4、深拷贝的方法
5、深拷贝方法中JSON.Stringfiy()有什么坏处
六、栈内存和堆内存的总结
| 栈内存 | 堆内存 | | —- | —- | | 存储基础数据类型 | 存储引用数据类型 | | 按值访问 | 按引用访问 | | 存储的值大小固定或者是有范围上限 | 存储的值大小不固定,可动态调整 | | 由系统自动分配内存空间 | 由代码进行指定分配 | | 空间小,运行效率高 | 空间大,运行效率相对较低 | | 先进后出,后进先出 | 无序存储,可根据引用直接获取 |
