js具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存.具体到浏览器中的实现,通常有2个策略.
引用计数(reference counting)
引用计数的含义就是跟踪记录每个值被引用的次数.当声明了一个变量A并将一个引用类型的值(valueA)赋给该变量时,valueA的引用计数是1.如果valueA又被赋值给另一个变量B,则valueA的引用次数是2.相反如果变量B的值是另外的一个值(valueB),那么valueA的引用次数是1,valueB的引用次数是1.
当valueA的引用次数是0的时候,说明没有办法再访问这些值了,因而可以将其占用的内存回收.这样,当垃圾收集器下次运行时,就会释放这部分内存.
这种策略有个严重的问题,就是循环引用
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
这里例子中,objectA和objectB通过各自的属性相互引用.这两个对象的引用次数都是2.假如这个函数被重复多次调用,就会导致大量的内存得不到回收.因此后来的浏览器弃用了这种策略,转而采用另一种策略.
标记清除(mark-and-sweep)
通俗的讲,就是当变量进入执行环境的时候标记为"进入环境",离开执行环境的时候标记为"离开环境".这是什么意思呢?
function foo(){
var a = 1;
}
foo();
上面例子中,foo函数在执行的时候,申明了一个变量a, 这时候就将a变量标记为"进入环境",foo函数执行完后,将a变量标记为"离开环境".垃圾收集器在运行的时候,就会将标记为"离开环境"的变量从内存中清除.
性能问题
垃圾收集器是周期性运行的,而且如果为变量分配的内存数量很可观,那么回收工作量也是相当大的.在这种情况下,确定垃圾收集的时间间隔是一个非常重要的问题.
IE7发布的时候,其 JavaScript 引擎的垃圾收集例程改变了工作方式:触发垃圾收集的变量分配,字面量和(或)数组元素的临界值被调整为动态修正.IE7 中的各项临界值在初始时与 IE6 相等.如果垃圾收集例程回收的内存分配量低于 15%,则变量,字面量和(或)数组元素的临界值就会加倍.如果例程回收了 85%的内存分配量,则将各种临界值重置回默认值.
简单点说就是内存空间不足了,就执行垃圾回收,反之不执行.
管理内存
js并没有像c语言那样手动操作内存的机制.但是开发人员可以手动销毁一些变量,这样等到垃圾回收机制执行的时候,会释放更多的内存.这种做法一般适用于全局变量,因为局部变量会在执行环境结束后自动清除.
function createPerson(name){
var localPerson = new Object();
localPerson.name = name;
return localPerson;
}
var globalPerson = createPerson("Nicholas");
// 手工解除 globalPerson 的引用
globalPerson = null;
网友评论