欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于JS垃圾回收机制

程序员文章站 2022-09-03 21:30:47
一、垃圾回收机制的必要性 由于字符串、对象和数组没有固定大小,所以当它们的大小已知时,才能对它们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便它们能够被再用,否则,JavaScript ......

一、垃圾回收机制的必要性

       由于字符串、对象和数组没有固定大小,所以当它们的大小已知时,才能对它们进行动态的存储分配。javascript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便它们能够被再用,否则,javascript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。

  javascript的解释器可以检测到何时程序不再使用一个对象了,当它确定了一个对象是无用的时候,它就知道不再需要这个对象,可以把它所占用的内存释放掉了。

二、垃圾回收机制

  js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。

1、标记清除(常用) 

  当一块内存中的数据能够被访问时,垃圾回收器就认为"该数据能够被获得"。不能够被获得的数据,就会被打上标记,并回收内存空间。这种方式叫作标记---清除算法。

这个算法会设置一个全局对象,并定期地从全局对象开始查找,垃圾回收器会找到所有可以获得与不能获得的数据。

  工作流程:

   (1)垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。

   (2)去掉环境中的变量以及被环境中的变量引用的变量的标记。

   (3)再被加上标记的会被视为准备删除的变量。

   (4)垃圾回收器完成内存清除工作,销毁那些带标记的数据并回收它们所占用的内存空间。

  注意:在局部作用域中,当函数执行完毕后,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但在全局中,变量什么时候需要自动释放内存空间则很难判断,因此我们在开发时,应尽量避免使用全局变量。如果使用了全局变量,则建议不再使用它时,通过释放变量方式,以确保能够及时回收内存空间。

2、引用计数

  跟踪记录每个值被引用的次数。例当变量声明,第一次赋值时记为1,然后当这个变量值改变时,记录为0,将计数为0的回收。

  工作流程:

   (1)声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。

   (2)同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1.

   (3)当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1.

   (4)当引用次数变成0时,说明没办法访问这个值了。

   (5)当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。  

但是当循环引用的时候就会释放不掉内存。

1 function problem() {
2     var obja = new object();
3     var objb = new object();
4 
5     obja.someotherobject = objb;
6     objb.anotherobject = obja;
7 }

当obja和objb通过各自的属性相互引用,也就是说这两个对象的引用次数都是2。在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用域,函数执行完成之后,obja和objb还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露。

因为ie中的bom、dom的实现使用了com,而com对象使用的垃圾收集机制是引用计数策略。所以会存在循环引用的问题。

解决:手工断开js对象和dom之间的链接,赋值为null。ie9把dom和bom转换成真正的js对象了,所以避免了这个问题。