这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
- 由于考虑到内存性能问题,当我们不再需要某些内容时就要用Javacript引擎清理
可达性
- 这是JavaScript管理内存的概念
"可达"值:以某种形式可访问或可用的值,一定是存储在内存中的
0. 固有可达值不能被释放
- 当前执行的函数及相关调用链的局部变量和参数
- 全局变量
- 还有一些其他的,内部的。
这些值被称作——根
1. 判断值的可达
- 一个值可以通过引用链从根访问任何其它值
- 这里举个例子:
// user 具有对这个对象的引用
let user = {
name: "John"
};
上面的代码:user是全局变量,它引用了对象{name:"John"},这时候它是可达的
但是加上这句user = null ,对象{name:"John"}变成不可达的了,原因是没有了引用
。这时候垃圾回收器(在 JavaScript 引擎中有一个被称作 垃圾回收器 的东西在后台执行。)就认为它是垃圾数据进行回收,再释放内存
- 改变下思路,这里将
user = null换成let admin = user,这时候就是两个引用
只有将user和admin都重写成null才会被回收
- 相互关联的对象
现在来看一个更复杂的例子。这是个家庭:
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
代码的结构如图所示
这时移除两个引用:
delete family.father;
delete family.mother.husband;
变成
这里还是可达,实际应该将delete family.mother.husband 改为delete family.father.wife。因为,对外传入的引用对可达无影响,对内传入才有效
- 极端状况
上面的代码重写为family = null
这时
由此可见,几个对象相互引用,但外部没有对其任意对象的引用,这些对象也可能是不可达的,并被从内存中删除。
内部算法(mark-and-sweep)
- 假设有对象如下,
垃圾回收步骤:
- 垃圾收集器找到所有的根,并“标记”(记住)它们。
- 一层层遍历它们相关的引用标记,直到所有可达的(从根部)引用都被访问到。
- 没有被标记的对象都会被删除。