当我们创建对象、函数这些东西的时候,我们都需要一个内存去储存他们,即JS的内存管理其实是自动进行的,但是如果我们不需要这些东西的时候,JS是怎么知道的呢?又是怎么清理它们的呢?
JS中内存管理的主要概念是可达性(reachability),可达值是指保证那些可以被访问或者使用的值保存在内存中。比如一些固有值(roots)和可以通过引用和引用链从根访问到的值。那么这些可达值就无法被删除,剩下的其他值,就受到JS引擎中垃圾收集器的监视并删除。
举个例子:
let user = {
name: "John"
};
此时全局变量user
引用该对象{name: "John"}
。该对象的属性存储一个基元,因此将其绘制在对象内部。可是如果这个user
被覆盖user = null;
,那么这个引用就丢失了,即John变得不可达,没有对象能够访问他,也没有引用他,因此垃圾收集器就会将这个数据删除。
现在我们将引用从复制user
到admin
:
let user = {
name: "John"
};
let admin = user;
当我们再次执行user = null;
时,该对象虽然值为null
,但是我们仍然可以通过admin
全局变量访问,因此它还在内存中。可是如果我们也覆盖admin
,它就会被删除了。
再来个复杂的例子:
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
此时所有的对象都是可达的,但是我们现在要做的是删除family.father
这个引用,此时John还是可达的,那我们删除family.mother.husband
这个引用呢?答案还是一样,可是如果我们将它们都删除呢?那么此时John就只有传出的引用,没有传入的引用,说得通俗一些就是你认识你的偶像,可是你的偶像却不认识你,这个时候你只能被无情的删除了。
同样的代码,我们执行family = null;
会怎么样呢?此时就要引入一个概念即可达性概念,虽然家庭成员之间相互间都有传出和传入的引用,但是此时family
对象已经和根断开了,那么John和Ann以及他们之间的相互引用链接,都会被删除。
说完概念,具体垃圾回收是怎么执行的呢?
基本的垃圾收集算法称为“标记清除”。
它定期执行以下步骤:
- 垃圾收集器收取他们的根并对其进行“标记”。
- 访问并“标记”所有来自它们的引用。
- 访问标记的对象以及标记它们的引用。记住所有访问过的对象,以免将来再次访问同一对象。
- 依此类推,直到访问了所有可到达的引用(从根开始)。
- 把除了被标记以外的所有对象删除。
这就是垃圾收集工作原理的概念。
注意
- 垃圾收集是自动执行的。我们不能强迫或阻止它。
- 当对象可以访问时,它们会保留在内存中。
- 被引用与可(从根)访问不同:一堆相互链接的对象可能都不可访问。
文章来源在这
感谢观看哟
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!