一文看懂JS的垃圾收集系统
前言
关于JS的垃圾收集系统,我们很多人可能知道他是具有自动收集的机制,但是可能并没有深入了解,或者怀疑了解这玩意到底有什么好处。
自动垃圾收集
自动垃圾收集指的是执行环境会负责管理代码执行过程中所使用的内存,在C中手动跟踪内存使用是开发人员的一项基本任务,JS虽说实现了自动内存管理,但是并不意味着这种管理机制很复杂,相反其实很简单,JS中的垃圾收集器会按照固定的时间间隔取搜寻那些不在使用的变量,然后释放其内存。
看到这里,你可能已经发现了重点,没错怎么识别那些无用变量就成了一项十分关键的任务,目前浏览器中主要有两种方式实现。
标记清除
这是JS中最常用的方式,当变量进入环境时,他们会被标记为进入,同理离开时会被标记为离开。
具体如何标记有很多种方式,比如反转某个特殊的位。
一般来说,垃圾收集器运行时会位所有内存中的变量加上标记,然后他会去掉环境中的变量以及被环境中变量引用的变量,而在这之后所有再被加上标记的变量都是准备被删除的变量,原因是环境中的变量无法访问他们,于是那些带着标记的宝宝们就被无情收割并回收。
引用计数
这种方式相对于上一种用的就少多了,即跟踪记录每个值被引用的次数。
简单的说,当声明一个变量并把它赋值时,这个值的引用次数加一,不断叠加,一个值可以给多个变量使用,而当这个值的引用次数变成0时,意味着没有变量能访问这个值了,那么它的内存空间就可以被收回。
我个人乍一看这种方式其实更加科学合理,为什么用的这么少呢?
Netscape Navigation 3.0是最早这样做的,但是很快他就遇到了循环引用的问题,即对象A有指向B的指针,同理B也有一个指向A的,这样导致引用次数永远不会为0,因此很快被放弃了。
但是IE8还因为某种原因在用。
性能
除去判断变量何使可被回收,策略每隔多久执行一次也是十分重要的,IE7前因为这个问题损失惨重。这里不再详谈,具体可以自己搜一下,看看微软大牛们如何使用动态修正解决垃圾回收内存分配量的问题。
最后
由于JS自身的特性,分配给浏览器的内存往往要少于桌面应用,自然会需要更多的优化措施,如解除引用,这样不仅可以消除循环引用,对于垃圾收集也有很多好处。