JavaScript - 垃圾回收机制
2019-10-20 本文已影响0人
ElricTang
局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行结束。此时,局部变量就没有存在的必要了,因此可以释放它们的内存以供将来使用。
具体实现策略
一. 标记清除
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
二. 引用计数
- 引用计数的含义是跟踪记录每个值被引用的次数。
- 当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。
- 如果同一个值又被赋给另一个变量,则该值的引用次数加 1。
- 相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。
- 当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。
引用计数的问题:循环引用可能导致内存泄漏
function problem(){
var obj1 = {};
var obj2 = {};
obj1.link2obj2 = obj2;
obj2.link2obj1 = obj1;
}
- 在使用标志清除策略时,当函数执行完毕,因为离开了作用域,变量obj1和obj2都会被回收。
- 但在用引用计数策略时,由于循环引用,两个变量的计数都是2,而且没法释放(计数无法变为0)。如果函数被大量调用,会导致大量内存被占用。
- 在IE9以下版本,IE的DOM和BOM对象使用的是C++的COM对象实现,COM就是使用引用计数策略。这导致了IE9下浏览器,在对象与DOM对象互相引用时也存在内存问题。
var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.someObject = myObject;
- 消除引用
myObject.element = null;
element.someObject = null;