详解js垃圾回收机制

垃圾回收

js 具有垃圾回收机制

原理:

找出那些不再继续使用的变量,然后释放其占用的内存,垃圾回收器会按照固定的时间间隔(或者代码中预定的收集时间)周期性的执行这一操作
垃圾收集器必须跟踪那个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存。

1. 标记清除

思想是给当前不使用的值加上标记,然后再回收其内存

垃圾收集器在运行的时候会给存储在内存中的所有变量加上标记,然后他会去掉环境中的变量以及被环境中变量引用的变量的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收它们所占的内存空间

2. 引用计数

思想是:跟踪每个值被引用的次数
  • 当声明了一个变量并将一个引用类型的值赋给该变量时,这个值的引用次数就是1
  • 如果同一个值被赋给了另一个变量,则该值的引用次数加一
  • 如果包含对这个值引用的变量又取得了另一个值,则这个值的引用次数减一
  • 当这个值的引用次数变为0时,则说明没有办法再访问这个值了,因此就可以将这个值占用的内存空间回收回来
  • 当下次垃圾收集器运行时,就会释放那些引用次数为0的值所占的内存
存在的问题:循环引用导致不能回收
function problem(){
	var objedt1 = new object();
	var objedt2 = new object();

	object1.someOtherObject = object2;
	object2.someOtherObject = object1;
}

object1和 object2通过各自的属性相互引用,这两个对象的引用次数都是2。当函数执行完毕后,他俩还继续存在,因为他们的引用次数永远不是0,假如这个函数被重复调用,就会导致大量内存得不到回收

为了避免这种问题,最好在不使用他们的时候手工断开原生js 对象和Dom 之间的连接

	object1.someOtherObject = null;
	object2.someOtherObject = null;

将变量设置为null 意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收他们占用的内存

性能问题

垃圾收集器是周期性运行的,如果为变量分配的内存数量很可观,那么回收工作量也是相当大的。

工作方式:触发垃圾收集的变量分配字面量或者数组元素的临界值被调整为动态
  • 如果垃圾收集例程回收的内存分配量低于15%,则变量,字面量和数组元素的临界值就会加倍
  • 如果例程回收了85%的内存分配量,则将各种临界值重置回默认值
注意
  1. 在IE中,调用window.CollectGarbage()方法会立即执行垃圾收集
  2. 在高版本中,调用window.opera.collect()会启动垃圾收集例程

管理内存

分配给Web 浏览器的可用内存数量通常要比分配给桌面应用程序的少。
目的是防止运行js网页耗尽全部系统内存而导致系统崩溃

内存限制问题不仅会影响给变量分配内存,同时会影响调用栈以及在一个线程中能够同时执行的语句数量

解除引用

使用将值设置为null 来释放其引用(适合于大量的全局变量和全局对象的属性)
局部变量会在它们离开执行环境时自动被解除引用

function createPerson(name){
	var localPerson = new object();
	localPerson.name = name;
	return localPerson; //因为是局部变量所以无需解除
}
var globalPerson = createPerson("zhangsan");
//手动解除引用
globalPerson = null;
解除的目的

解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用真正的目的是让值脱离执行环境,以便垃圾收集器下次运行时将其回收
解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效的回收内存,应该及时解除不再使用的全局对象,全局对象属性以及循环引用变量的引用。

猜你喜欢

转载自blog.csdn.net/Welkin_qing/article/details/88628801