1.简单介绍
js中存在着自动垃圾收集机制,也就是说执行环境会复制管理代码执行过程中使用的内存,不需要开发人员去手动跟踪。
垃圾收集机制的原理:找出不再使用的变量,释放其占用的资源。
为什么需要垃圾回收?:防止内存泄露,一些不再需要使用的变量仍然保存在内存中,就会造成内存泄露问题。
垃圾收集器必须跟踪某个变量是否有用,对于不需再使用的变量打上标记以便回收,用于标识无用变量的策略通常有两种:标记清除,引用计数
2.标记清除
当变量进入环境的时候,就将这个变量标记为“进入环境”。从逻辑上来说,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到这些变量。当变量离开环境后,将变量标记为“离开环境”
垃圾收集器在运行的时候会給存储在内存中的所有变量都加上标记(可以使用任何标记方式),然后,它会去掉环境中的变量及被环境中的变量引用的变量的标记,在这项工作完成之后再被加上标记的变量就视为准备删除的变量。最后,垃圾收集器完成内存清除工作,销毁掉带标记的值并回收它们所占用的空间。
大部分浏览器使用的都是标记清除式的垃圾收集策略,只不过时间间隔可能会不同。
function test(){ var a=0; var b=0; //a,b被标记为进入环境 } test(); //函数执行完毕,a,b被标记为离开环境。等待垃圾收集器回收
3.引用计数
这个策略在现在的浏览器中不常见,引用计数是指跟踪记录每个值被引用的次数。
当声明了一个变量并且将一个引用类型值赋值给这个变量时,该值得引用次数就是1,。如果同一个值又被赋给另一个变量,则该值的引用次数加一。如果包含对这个值引用的变量取了别的值,则该值的引用次数减一。当该值的引用次数变为0的时候,说明没有办法访问这个值了,因此就可以将其占用的空间回收。当垃圾收集器再次运行的时候,就会释放那些引用次数为0的值所占的内存。
但是这个策略有一个严重的问题:循环引用。
循环引用是指对象a包含一个指向对象b的指针,而对象b也包含一个指向对象a的引用。
function problem(){ var obA = new Object(); var obB = new Object(); ObA.someOtherObject = ObB; ObB.anotherObject = ObA; }
在这个例子中,,obA和obB通过各自的属性相互引,它们的引用次数都为2。
如果我们采用标记清除策略,函数执行完毕以后这两个对象就离开了作用域,会被垃圾收集器视为准备删除的变量。
但是如果采用引用计数策略,当函数执行完毕后,它们还将继续存在,因为它们的引用次数不可能减为0。假如重复多次调用这个函数,就会造成大量内存得不到回收,导致内存泄露。
原文:https://www.cnblogs.com/hwinter/p/13411397.html