JS垃圾回收机制
1.概述
JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着。垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。
C#、Java、JavaScript有自动垃圾回收机制,但C++和C没有。在JS中,JS的执行环境会负责管理代码执行过程中所使用的内存。
2.变量的生命周期
当一个变量的生命周期结束之后它所指向的内存就应该被释放。JS有两种变量,全局变量和在函数中产生的局部变量。局部变量的生命周期在函数执行过后就结束了,此时便可以将它引用的内存释放(即垃圾回收),但全局变量的生命周期会持续到浏览器关闭页面。
3.JS垃圾回收标志
JS执行环境中的垃圾回收器有两种方式检测那块内存可以被回收:标记清除(mark and sweep)、引用计数(reference counting)。
3.1 标记清除(mark and sweep)
大部分浏览器以此方式进行垃圾回收,当变量进入执行环境(函数中声明变量)时,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候将其标记为“离开环境”,在离开环境之后还有的变量就是需要被删除的变量。标记方式不定,可以是某个特殊位的反转或者维护一个列表等。
垃圾收集器给内存中的所有变量加上标记,然后去掉环境中的变量和环境中的变量所引用的变量的标记。在此之后再被加上标记的变量就是应该被回收的变量,因为环境中的变量已经无法访问到这些变量。
3.2 引用计数(reference counting)
这种方式常常会引起内存泄漏,低版本的IE使用这种方式。这种方式的机制为:跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个值时该值的引用次数便减1。当该值的引用次数为0时就会被回收。
该方式会引起内存泄漏的原因是他不能解决循环引用的问题:
function sample{
var a = {};
var b = {};
a.prop = b;
b.prop = a;
}
这种情况下调用sample函数,a和b的引用计数都是2,会使这部分内存永远不会被释放,即内存泄漏。
低版本IE中有一部分对象并不是原生JS对象。例如,其BOM和DOM中的对象就是使用C++以COM(Component Object Model)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。
因此即使IE的js引擎是用的标记清除来实现的,但是js访问COM对象如BOM,DOM还是基于引用计数的策略的,也就是说只要在IE中设计到COM对象,也就会存在循环引用的问题。
参考文献
- sunhuahuaa
- https://www.cnblogs.com/sunhuahuaa/p/7655587.html