写在前面:众所周知,当我们想学习某些知识或者解决某些技术难题的时候,网络或者书籍上就会有一万个大牛为你解惑答疑。那么我为什么还要关公面前舞大刀,花费大量的时间去写这些文章呢?目的有两个,第一是想通过写写技术文档,来提升自己的表达总结能力;第二则是因为好记性不如烂笔头的道理,短时间内可能会觉得这是一个浪费时间浪费精力的事情,但是从长远来看,这无疑会加深我们对知识的理解并巩固我们的知识体系。
栈内存
栈内存由编译器自动分配与释放。我们可以直接操作栈内存中的值。js中的基本数据类都有固定的大小,被分配到栈内存中。这些基本类型的值都是按值引用。将一个基本类型的值赋值给另外一个基本类型时,会为这个新的值重新创建一个值并保存在栈内存中。
堆内存
堆内存是链表结构的类型,可以动态分配大小,js引用类型占用内存空间的大小不固定,存储在堆内存中。由于JS不允许直接访问堆内存中的位置,因此我们不能直接操作js的引用类型。而是生成一个指针,并将它放到栈内存中,通过这个指针来操作引用类型。
垃圾回收
现在浏览器基本都在使用标记-清除的算法来执行垃圾回收。而不是使用引用计数的方式,因为引用计数方式无法释放循环引用结构的内存占用。 标记清除算法的核型概念是:从根部(在JS中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收。
内存泄漏
对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。 对于不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)
常见的内存泄漏
- 不合理的计时器
- 被共享的闭包作用域
- 脱离dom引用
- 意外的全局变量
参考: