javascript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。而C,C++之类的语言则会麻烦一些,需要手动跟踪内存的使用情况。
但是在编写JavaScript代码的时候,大部分的时候,就不用再关心内存的问题,因为所需内存的分配以及无用内存的回收完全实现自动管理。
这种垃圾回收机制的原理:找到不再继续使用的变量,然后释放它们占用的内存。所以,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。
局部变量的正常生命周期
局部变量只会在函数执行过程中存在,在这个过程中,会为局部变量再栈或者堆内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行结束。
这种情况比较好判断变量的存在必要性,但在某些情况下就不容易判断,垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用内存。用于标识无用变量的策略可能会因实现而异,但具体到浏览器中的实现,则通常有两个策略。
一、标记清除(常用)
1.标记清除就是给变量做标记。当变量进入环境的时候,就将这个变量标记为“进入环境”。当变量离开环境的时候,将其标记为离开环境。
可以用任何方式来标记变量,比如:
- 可以通过翻转某个特殊的位来记录一个变量何时进入环境
- 使用一个“进入环境的”变量列表
- 使用一个“离开环境的”变量列表
....
可以使用上述方法来跟踪那个变量发生了变化。有时候标记变量的方式不太重要,重要的是采取什么策略
2.原理
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,可以使用任何方式进行标记。然后它会去掉环境中的变量以及被环境中变量引用的变量的标记。在此之后再被加上标记的变量将被作为准备删除的变量。最后垃圾收集器会完成内存清除工作,即销毁那些带标记的值并回收它们所占用的内存空间。
二、引用计数(不太常见)
含义:跟踪记录每个值被引用的次数。
当声明了一个变量并将一个引用类型值赋值给该变量,则这个值的引用次数加1,如果同一个值又被赋值给另一个变量,则该值的引用次数加1.相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1.当这个值的引用次数减为0的时候,就没有办法再访问它了,当垃圾收集器,下次运行的时候,就会释放那些引用次数为0的值所占用的内存。
Netscape Navigator 3.0最早使用引用计数策略的浏览器,但遇到了一个严重的问题:循环引用
- 定义:
对象A中包含一个指向对象B的指针,对象B中也包含一个指向对象A的引用。
举例
function problem(){ var objectA = new Object(); var objectB = new Object(); objectA.someOtherObject = objectB; objectB.anOtherObject = objectA; //objectA和objectB这两个对象的引用次数都为2. }
上述如果使用标记清除就没有问题,引用计数就会出现循环引用的问题。
后来Netscape Navigator 4.0放弃了引用计数清除策略,但是还是存在问题。
BOM和DOM中的对象问题