Javascript 垃圾回收
内存管理Javascript是自动完成的,对用户来说是透明的。我们创建原始类型、对象、函数等,所有这些都需要占用内存。当一些对象不再被需要时,Javascript引擎是如何发现并清除?
能达性(Reachability)
Javascript内存管理主要概念是能达性。简单说,“能达”是那些可被访问或使用值,他们需保证存储在内存中。
1、继承可达值,他们显然不能被删除。
- 当前函数中局部变量和参数
- 在当前嵌套调用链的其他函数使用的变量或参数
- 全局变量
2、从一个根引用或引用链可到达的值。
如一个对象有内部变量被另一个对象的属性引用,则该对象是能到达的。
Javascript引擎有后台进程称为垃圾回收,它监控所有对象并删除那些不可到达的对象。
示例1
// user has a reference to the object
let user = {
name: "John"
};
user = null;
这里全局对象user引用对象{name:”John”},如果user被重写,则引用丢失,现在对象{name:”John”}变得不可达,没有办法访问,没有引用指向它,垃圾回收程序将丢弃数据释放内存。
// user has a reference to the object
let user = {
name: "John"
};
let admin = user;
user = null;
这段代码,有两个引用指向对象,删除一个,仍然有admin指向对象,因此对象不会被回收。
相互链接对象
看下面一个复杂的示例
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
函数marry缔结两个对象,两个对象之间相互引用,然后返回一个新对象包含他们一起,内存结构如下:
现在所有对象都可到达,现在删除变量。
delete family.father;
delete family.mother.husband;
删除其中任何一个都不能Johe对象(简写)不可到达,但现在删除两个,我们能看到John对象不再有输入引用。
向外引用不重要,只有输入引用会让对象可达。所以John对象现在不能到达,将被垃圾回收,其所有数据也不能被访问。回收后内存结构如下:
孤岛
相互链接的孤岛对象可能变成不可到达,同样也会被回收,下面代码示例:
family = null;
内存结构变成:
显然John对象和Ann对象相互引用,互为输入引用,但这是不够的,family对象已经从根断开,不再有引用指向孤岛对象,所有整个孤岛将被回收。内部算法这里不再详述。
总结
- 垃圾回收是自动执行的,我们无法阻止。
- 当对象是可到达时,保留在内存中。
- 被引用与可到达不同(从一个根),如相互引用对象整体不能到达。
现代引擎如V8实现了垃圾回收的高级算法,优化性能,快速准确回收。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/68483119