因为字符串、对象和数组没有固定的大小,所以只有在知道动态存储分配的大小时才能执行。每次JavaScript程序创建字符串、数组或对象时,解释器必须分配内存来存储该实体。只要像这样动态地分配内存,它最终将被释放以便可以重用,否则JavaScript解释器将消耗系统中的所有可用内存并导致系统崩溃。
这篇文章解释了为什么系统需要垃圾收集。与C/C++不同,JS有自己的垃圾收集机制。javascript解释器可以检测程序何时不再使用对象。当他确定一个物体是无用的时,他知道它不再需要了,可以释放它所占据的记忆。例如:
var a=之前;
var b=覆盖a;
var a=b;//重写a
运行此代码后,“before”字符串将丢失其引用(以前由a引用)。当系统检测到这个事实时,它会释放字符串的存储空间,以便可以重用。
二。垃圾回收利用原理分析
现在,主要浏览器通常使用两种垃圾收集方法:标签清除和引用计数。
1。标记间隙
这是JavaScript中最常见的垃圾收集方式。当变量进入执行环境时,它被标记为入口环境。从逻辑上讲,进入环境的变量永远无法从内存中释放,因为只要执行流进入相应的环境,就可以使用它们。当变量离开环境时,它被标记为“离开环境”。
当垃圾收集器运行时,它标记存储在内存中的所有变量。然后,它删除环境中的变量和环境中变量引用的标记。之后标记的变量被视为准备删除,因为环境中的变量不再可访问。最后。垃圾收集器执行内存清理、销毁标记值并回收它们占用的内存。
对于这一部分,我建议阅读汤姆叔叔的文章,详细解释一些关于范围链的知识。在阅读之后,您几乎可以知道哪些变量将被标记。
2。参考计数
另一种不太常见的垃圾收集策略是引用计数。引用计数意味着跟踪每个值被引用的次数。当变量被声明并且引用类型被分配给该变量时,对该值的引用数为1。相反,如果包含对该值的引用的变量生成另一个值,则对该值的引用数将减少1。当引用数为零时,意味着无法再次访问该值,因此可以恢复它所占用的内存空间。这样,下次垃圾收集器运行时,它将释放具有零引用的值所占用的内存。
但是这个方法有问题。让我们看看下面的代码。
复制代码
函数问题()。{
var obja=新对象();
var objb=新对象();
obja.someOtherObject=objb;
objb.anotherObject=obja;
}
复制代码
在本例中,obja和objb通过各自的属性相互引用;垃圾分类也就是说,对两个对象的引用数为2。在使用引用计数策略中,由于两个对象在函数执行后都离开作用域,因此在函数执行后,obja和objb将继续存在,因为它们的引用数永远不会为零。如果大量存在这样的交叉引用,可能会导致大量内存泄漏。
我们知道IE中的一些对象不是本机JavaScript对象。例如,它们的BOM和DOM中的对象使用C++到COM(组件对象)。
模型(组件对象)以对象的形式实现,COM对象的垃圾收集器是引用计数策略。因此,即使IE的javascript引擎实现了标记清除,javascript还是基于引用计数策略访问COM对象。坦率地说,只要COM对象涉及到IE,就存在循环引用的问题。请看下面的简单示例:
var元素=文档。getElementByID(“some_element”);
var myobj=新对象();
MYOBJ.元素=元素;
元素。someObject=myobj;
在上面的示例中,在dom元素和本机javascript对象(myobj)之间建立循环引用。其中,变量myobj有一个名为element的属性指向元素,而变量元素有一个名为someobject的属性指向myobj。由于循环引用,即使从页面中删除示例中的DOM,也不会回收内存。
但是,上述问题并不能解决,我们可以手动切断它们的循环引用。
MYOBJ.元素=空;
元素。someObject=空;
这样,T