垃圾回收

可达性(Reachability)

“可达”值是那些以某种方式可访问或可用的值,它们一定是存储在内存中的。
_
1.固有的可达值的基本集合,这些值明显不能被释放。

  • 当前函数的局部变量和参数。
  • 嵌套调用时,当前调用链上所有函数的变量与参数。
  • 全局变量。
  • (还有一些内部的)

这些值被称作 根(roots)

2.如果一个值可以通过引用或引用链从根访问任何其他值,则认为该值是可达的。
比方说,如果局部变量中有一个对象,并且该对象有一个属性引用了另一个对象,则该对象被认为是可达的。而且它引用的内容也是可达的。

垃圾回收器 监控着所有对象的状态,并删除掉那些已经不可达的。

例子

  1. // user 具有对这个对象的引用
  2. let user = {
  3. name: "John"
  4. };
  5. // 如果 user 的值被重写了,这个引用就没了
  6. user = null;
  7. // 对象 {name:"John"} 变成不可达的了,因为没有引用了,不能访问到它了。

两个引用

  1. // user 具有对这个对象的引用
  2. let user = {
  3. name: "John"
  4. };
  5. let admin = user;
  6. user = null;
  7. console.log(admin);
  8. // {name: "John"}
  9. admin = null;
  10. // 对象被删除

相互关联的对象

  1. function marry(man, woman) {
  2. woman.husband = man;
  3. man.wife = woman;
  4. return {
  5. father: man,
  6. mother: woman
  7. }
  8. }
  9. let family = marry({
  10. name: "John"
  11. }, {
  12. name: "Ann"
  13. });

image.png

  1. // 移除两个引用:
  2. // 移除一个并不能时John不可达,移除两个才能实现John不可达,并且John会被从内存中删除。
  3. delete family.father;
  4. delete family.mother.husband;

image.png
image.png

无法到达的岛屿

几个对象相互引用,但外部没有对其任意对象的引用,这些对象也可能是不可达的,并被从内存中删除。
image.png
垃圾回收的基本算法被称为 “mark-and-sweep”。
定期执行以下“垃圾回收”步骤:

  • 垃圾收集器找到所有的根,并“标记”(记住)它们。
  • 然后它遍历并“标记”来自它们的所有引用。
  • 然后它遍历标记的对象并标记 他们的 引用。所有被遍历到的对象都会被记住,以免将来再次遍历到同一个对象。
  • ……如此操作,直到所有可达的(从根部)引用都被访问到。
  • 没有被标记的对象都会被删除。

可以将这个过程想象成从根溢出一个巨大的油漆桶,它流经所有引用并标记所有可到达的对象。然后移除未标记的。
_

总结

  • 垃圾回收是自动完成的,我们不能强制执行或是阻止执行。
  • 当对象是可达状态时,它一定是存在于内存中的。
  • 被引用与可访问(从一个根)不同:一组相互连接的对象可能整体都不可达。