ECMAScript垃圾收集
JavaScript具有强大的垃圾回收功能,执行环境负责管理代码执行过程中使用的内存。其基本原理是:在执行环境中找出那些不再继续使用的变量,然后释放其占用的内存。垃圾收集器会按照系统编写号的时间间隔,周期性地执行操作。
局部变量的生命周期
一个函数中局部变量正常生命周期,局部变量只在函数执行的过程中存在,而在执行的过程中,会为,局部变量在栈或者堆内存上分配内存空间,以便存储他们的值。然后再函数中使用这些变量,直至函数执行结束。在这个时候,局部变量就没有存在的必要了,因此可以释放它们的内存供将来变量使用。
function car() { var wheel = 100; return console.log(wheel);// } car(); console.log(wheel);//不能够访问,输出错误
垃圾收集器想要收集废掉的变量,可以在其废掉的变量打上标记,用于收回占用的内存,标识废掉的变量策咯会因实现而不同,在浏览器中实现,通常有两种策咯。
标记清除
这个JavaScript中最常用的垃圾收集方式,每当一个变量进入环境,就将这个变量标记为“进入环境“。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就会使用到,而当变量离开环境时,则标记为”离开环境“。
引用计数
引用计数一般的原理是:声明一个变量,则该值的引用次数加1,如果同一个值又被赋给另一个变量,则该值的引用吃书加1,相反,如果包含对这个值引用的变量又取得了另外一个值,那么这个值引用次数减1,当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间收回来。
问题:循环引用
循环引用指的是,A对象中包含一个指向B对象的指针,而对象B中也包含一个指向对象A的引用。
function problem() { var objectA = new Object(); var objectB = new Object(); objectA.prototype1 = objectB; objectB.prototype2 = objectA; }
上述代码中,每当执行完毕后,构造的两个对象还会继续存在,因为它们的引用计数策咯实现不会是0。重复调用会产生大量的内存无法收集。
下面简单的例子,展示了使用COM对象导致的循环引用问题:
var element = document.getElementById("some_element"); var myObject = new Object(); myObject.element = element; element.someObject = myObject;
这个例子,DOM元素element与一个原生JavaScript对象myObject之间创建了引用。myObject的element属性指向element对象;而变量element也有一个属性叫someObject指向myObject,由于存在这个循环引用,即使例子中的DOM从页面中移除,它也永远不会被回收。
怎么解决这个问题呢?
在不使用它们的时候手工断开原生JavaScript对象与DOM之间的连接:
myObject.element = null; element.someObject = null;
将变量设置null,可以切断与它之前的连接,在下次运行时就会删除这些值并回收它们占用的内存。
事实上JavaScript是一门具有自动垃圾回收机制的编程语言,我们不必关心内存分配问题。
总结:
- 离开作用域的值将被自动标记为可回收,因此将在垃圾收集期间被删除。
- 标记清除是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后回收。
- 引用计数,思想是跟踪记录所有值被引用的次数。
- 解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果您喜欢或者有所启发,欢迎添加收藏,一起加油学习啊。