垃圾回收
可达性(Reachability)
“可达”值是那些以某种方式可访问或可用的值,它们一定是存储在内存中的。
_
1.固有的可达值的基本集合,这些值明显不能被释放。
- 当前函数的局部变量和参数。
- 嵌套调用时,当前调用链上所有函数的变量与参数。
- 全局变量。
- (还有一些内部的)
这些值被称作 根(roots)。
2.如果一个值可以通过引用或引用链从根访问任何其他值,则认为该值是可达的。
比方说,如果局部变量中有一个对象,并且该对象有一个属性引用了另一个对象,则该对象被认为是可达的。而且它引用的内容也是可达的。
垃圾回收器 监控着所有对象的状态,并删除掉那些已经不可达的。
例子
// user 具有对这个对象的引用let user = {name: "John"};// 如果 user 的值被重写了,这个引用就没了user = null;// 对象 {name:"John"} 变成不可达的了,因为没有引用了,不能访问到它了。
两个引用
// user 具有对这个对象的引用let user = {name: "John"};let admin = user;user = null;console.log(admin);// {name: "John"}admin = null;// 对象被删除
相互关联的对象
function marry(man, woman) {woman.husband = man;man.wife = woman;return {father: man,mother: woman}}let family = marry({name: "John"}, {name: "Ann"});

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


无法到达的岛屿
几个对象相互引用,但外部没有对其任意对象的引用,这些对象也可能是不可达的,并被从内存中删除。
垃圾回收的基本算法被称为 “mark-and-sweep”。
定期执行以下“垃圾回收”步骤:
- 垃圾收集器找到所有的根,并“标记”(记住)它们。
- 然后它遍历并“标记”来自它们的所有引用。
- 然后它遍历标记的对象并标记 他们的 引用。所有被遍历到的对象都会被记住,以免将来再次遍历到同一个对象。
- ……如此操作,直到所有可达的(从根部)引用都被访问到。
- 没有被标记的对象都会被删除。
可以将这个过程想象成从根溢出一个巨大的油漆桶,它流经所有引用并标记所有可到达的对象。然后移除未标记的。
_
总结
- 垃圾回收是自动完成的,我们不能强制执行或是阻止执行。
- 当对象是可达状态时,它一定是存在于内存中的。
- 被引用与可访问(从一个根)不同:一组相互连接的对象可能整体都不可达。
