js的垃圾清理机制
今天去面试,遇到了这个问题,之前是有看过想过相应资料,不过到时直接语塞了,回来翻看一些资料,总结如下:
1 原理
找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔,或是咱们在代码预订的收集时间,去周期性的执行这个操作,完成垃圾的清理。
2 局部变量的生命周期
在函数执行的过程中,才存在有局部变量,在这个过程中,浏览器引擎会为局部变量在栈或是堆内存上分配相应的空间,以便存储这些值。在函数执行结束后,局部变量就没有存在的必要了,因此可以释放它们所占用的内存以供将来使用。这种情况下回比较好判断变量有没有必要存在了,但是作用域还没有结束,当前变量还被其他地方调用了,那么垃圾收集器就得跟踪这些变量哪个有用哪个没用,做上相应的标记。
3 垃圾清理实现策略一:标记清除
当变量进入环境时,如在函数中var一个变量,此时将这个变量标记为进入环境,当变量离开环境的时候,则将其标记为离开环境,可以通过翻转某一个位来标记一个变量何时进入了环境。但标记不是重点,重点是标记了之后怎么来将其处理。垃圾收集器会在运行的时候给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量以及被环境中的变量应用的标记,在此之后再把加上标记的变量都将被视为准备删除的变量。最后,垃圾收集器完成内存的清楚工作,销毁那些带标记的值并收回它们所占用的内存空间
4 垃圾清理实现策略二:引用计数
跟踪记录每个值被引用的次数,当这个值的引用次数变成0的时候,说明没有办法再访问这个这个值,就将其占用的内存空间收回来,下次再运行垃圾收集器的时候,就会释放哪些引用次数为0的值所占用的内存了。
但存在的一个问题是,如果有循环引用,即A有个指针指向B,B也有一个指针指向A,在采用标记清楚策略的实现中,这将是个噩梦。如果DOM元素和原生JS对象之间创建了循环引用,那就带来内存泄露的问题,解决方法是把DOM和BOM对象转换成真正的JS对象。
5 垃圾收集的时间间隔
原来IE的垃圾收集器的启动方式是,当内存分配量达到256个变量、4096个对象字面量和数组元素或是64kb的字符串这三者任何一个临界值时,就开始启动垃圾收集器。但一个脚本中可能会在其生命周期中一直保有那么多变量,那么垃圾收集器就得一直的去运行,那导致的性能问题是很严重的。所以后面的优化方法是:触发垃圾收集的变量分配的临界值被调整为动态修正