JavaScript 垃圾收集
垃圾收集
JavaScript有自动垃圾收集机制,找出不再继续使用的变量,然后释放其占用的内存。
两个策略
标记清除(mark-and-sweep)
几句话概括:
- 当变量进入环境,就将这个变量标记为“进入环境”
- 从逻辑上讲,永远不能释放进入环境的变量所占用的内存
- 当变量离开环境时,就被标记为“离开环境”
- 先把内存中所有的变量加上标记,然后把环境中的变量和被环境中变量所引用的变量的标记去掉,剩下被加上标记的变量就视为准备删除的变量。
引用计数(reference counting)
含义:跟踪记录每个值被引用的次数
几句话概括:
- 当声明一个变量,并且把一个引用类型的值保存到该变量中,这个值的引用次数为1;
- 如果同一个值又赋值给另外一个变量,这个值的引用次数就加1;
- 如果某个保存这个值的变量取得了另外一个值,则这个值的引用次数减1;
- 当这个值的引用次数变成0,就可以把它占用的内存空间回收回来。
循环引用
循环引用的例子
对象A的某个属性指向对象B,且对象B的某个属性指向对象A
function example(){
var objA = new Object(); // 对象A的引用次数为1
var objB = new Object(); // 对象B的引用次数为1
objA.a = objB; // 对象B的引用次数+1,为2
objB.b = objA; // 对象A的引用次数+1,为2
}
这样,两个对象的引用次数都为2,当example函数执行完毕后,它们的引用次数都不会是0,所以这两个对象还会继续存在。那其占用的内存就得不到释放。
解除引用
确保占用最少的内存可以让页面获得更好的性能。优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。
一旦数据不再有用,最好通过将其值设置为null来释放其引用;
解除引用适用于大多数全局变量和全局对象的属性,因为局部变量会在离开执行环境时自动解除引用。
function example(name){
var localPerson = new Object();
localPerson.name = name;
return localPerson; // 退出环境时,自动解除引用。
}
var globalPerson = example('hua');
globalPerson = null; // ***手动解除,解除引用;
解除一个值的引用,并不是说就自动回收了该值所占用的内存;而是让该值脱离执行环境,在垃圾收集器下次运行时可以回收该值。