关于JS垃圾回收机制
一、垃圾回收机制的必要性
由于字符串、对象和数组没有固定大小,所以当它们的大小已知时,才能对它们进行动态的存储分配。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对象了,所以避免了这个问题。
上一篇: 诸葛亮死后为什么要人抬棺绳断下葬 这里边有什么说法吗
下一篇: 我坐过站了怎么办