垃圾回收 - Object 基础

  1. 可达性
  2. 一个简单例子
  3. 相互引用
  4. 孤岛内存
  5. 总结
  6. 参考

JavaScript 的内存管理是自动的、无形的。

可达性

“可达” 的值是那些以某种方式可访问或可用的值。它们一定是存储在内存中的。

  1. ** 确定可达的值 **:
  • 当前执行函数的局部变量和参数。
  • 嵌套调用时,调用栈上的所有函数的变量与参数。
  • 全局变量
  • 其他?
    以上值称为 roots
  1. 如果一个值可以从 roots 开始沿着引用链访问到,则认为此值是可达的。比方说,如果全局变量中有一个对象,并且该对象有一个属性引用了另一个对象,则 该 对象被认为是可达的。而且它引用的内容也是可达的。

一个简单例子

// user 具有对这个对象的引用
let user = {
    name: "John"
};

如果 user 的值被重写了,这个引用就没了:

user = null;

user 原本指向的 Object 对象实例变成不可达的了。因为没有引用了,就不能访问到它了。垃圾回收器会认为它是垃圾数据并进行回收,然后释放内存。
所以,当对象没有没任何引用指向时,就会被回收。

相互引用

运行以下代码:

function marry(man, woman) {
    woman.husband = man;
    man.wife = woman;
    return {
        father: man,
        mother: woman
    }
}
let family = marry({
    name: "John"
}, {
    name: "Ann"
});

产生的内存结构:

当多个引用相互引用时,删除一个引用可能不会造成对象不可达。
同时删除 father 与 husban 这两个引用会导致对象 John 被删除。
如下图:

因为对外引用不重要,只有传入引用才可以让对象是可达的。所以,John 现在是不可达的,并且将被从内存中删除,同时 John 的所有数据也将变得不可达。
进过垃圾回收后:

孤岛内存

几个对象相互引用,但是没有外部引用指向他们中的任意一个。这些相互引用的对象是不可达的,将会被从内存中删除。
还是上面的代码,如果运行:

family = null;

内存状态变成:

John 和 Ann 仍然连着,都有传入的引用。但是,前面说的 “family” 对象已经不再与根相连,没有了外部对这三个对象的引用,所以它变成了一座 “孤岛”,并且将被从内存中删除。

总结

主要需要掌握的内容:

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

参考


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。
我的空间