JavaScript 的内存管理是自动的、无形的。
可达性
“可达” 的值是那些以某种方式可访问或可用的值。它们一定是存储在内存中的。
- ** 确定可达的值 **:
- 当前执行函数的局部变量和参数。
- 嵌套调用时,调用栈上的所有函数的变量与参数。
- 全局变量
- 其他?
以上值称为roots
。
- 如果一个值可以从
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” 对象已经不再与根相连,没有了外部对这三个对象的引用,所以它变成了一座 “孤岛”,并且将被从内存中删除。
总结
主要需要掌握的内容:
- 垃圾回收是自动完成的,我们不能强制执行或是阻止执行。
- 当对象是可达状态时,它一定是存在于内存中的。
- 被引用与可访问(从一个根)不同:一组相互连接的对象可能整体都不可达。
参考
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。