标签:垃圾回收 ima 个数 类型 垃圾回收机制 编程 other 垃圾收集 没有
任何编程语言,在运行时都需要使用到内存,比如在一个函数中, var arr = [1, 2, 3, 4, 5]; 这么一个数组,就需要内存。
但是,在使用了这些内存之后, 如果后面他们不会再被用到,但是还没有及时释放,这就叫做内存泄露(memory leak)。如果出现了内存泄露,那么有可能
C语言是通过手动分配和释放内存的, 如通过malloc分配,通过free释放,这种方式是比较麻烦的。而java、c#、js等是为了解放程序员的负担,提出了程序自动释放内存,这种方式就是垃圾回收机制。
在js中,有引用计数和标记清除这两种垃圾回收机制。
即跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1; 相反,如果包含对这个值引用的变量又取得了另外一个值,那么这个值的引用次数就减1;当引用次数变为0的时候,则说明没有办法再访问到这个值了,所以,就可以把其所占用的内存空间给收回来。 这样,垃圾收集器下次再运行时,他就会释放哪些引用次数为0的值所占的内存。
但是,引用计数还是会存在问题的:
function problem() { var objA = new Object(); var objB = new Object(); objA.someOtherObject = objB; objB.anotherObject = objA; }
如上所示,objA指向内存中的引用类型,而这个引用类型的一个值又指向了另一个引用类型,这样,每个引用类型的引用次数都是2,且在引用类型之间形成了循环引用,这样,即使problem()函数执行完毕,把后期不再使用的局部变量objA和objB释放,但是因为引用类型的引用次数还是1,那么这两个引用类型还是不能被释放的,这就造成了内存泄露。 如下图所示:
所以说,我们所说的循环引用实际上是在堆中的两个引用类型之间的循环引用,如右边的两个箭头就构成了一个循环。
另外,由于BOM和DOM中的对象是使用C++以COM(Component Ojbect Model,组件对象)对象的形式实现的,而COM对象的垃圾回收机制是引用计数。 因此,即使IE的JavaScript引擎使用的是标记清除的策略,但是JavaScript访问的COM对象依然是基于引用计数的策略的,说白了,只要IE中涉及到了COM对象,就会存在循环引用的问题。 如下:
var element = document.getElementById("some_element"); var myObj =new Object(); myObj.element = element; element.someObject = myObj;
这个例子中,一个DOM元素和一个原生JavaScript对象之间建立了循环引用。这样,即使例子中的DOM从页面中移除,内存也不会被回收,但是,我们可以手动切断他们的循环引用:
myObj.element = null; element.someObject =null;
这样写代码就可以解决循环引用的问题,也就防止了内存泄露的问题了。
这是JavaScript中最常用的垃圾回收机制。当变量进入环境时,就标记这个变量为“进入环境”,逻辑上说,永远不能释放进入环境的变量所占用的内存,因为一旦进入环境就有可能随时用到他们,当变量离开环境的时候,将其标记为“离开环境”。
区别:可以看到,引用计数是实时的,即只要引用数为0,就会清除这变量,而标记清除是添加上标记之后,每隔一段时间回收哪些添加了离开环境标记的变量。
使用情况:不同的浏览器可能采用的回收机制不同,比如有的可能全部使用引用计数,有的全部使用标记清除。 但是,BOM、DOM采用的一定都是引用计数。
标签:垃圾回收 ima 个数 类型 垃圾回收机制 编程 other 垃圾收集 没有
原文地址:http://www.cnblogs.com/zhuzhenwei918/p/7586240.html