本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了垃圾回收的相关问题,垃圾回收是JavaScript的隐藏机制,下面一起来看一下,希望对大家有帮助。
|
本篇文章给大家带来了关于javascript的相关知识,其中主要介绍了垃圾回收的相关问题,垃圾回收是JavaScript的隐藏机制,下面一起来看一下,希望对大家有帮助。
【相关推荐:javascript视频教程、web前端】 一、前言垃圾回收是 二、何为垃圾代码执行在计算机的内存中,我们在代码中定义的所有变量、对象、函数都会在内存中占用一定的内存空间。在计算机中,内存空间是非常紧张的资源,我们必须时时刻刻注意内存的占用量,毕竟内存条非常贵!如果一个变量、函数或者对象在创建之后不再被后继的代码执行所需要,那么它就可以被称作垃圾。 虽然从直观上理解垃圾的定义非常容易,但是对于一个计算机程序来说,我们很难在某一时刻断定当前存在的变量、函数或者对象在未来不再使用。为了降低计算机内存的开销,同时又保证计算机程序正常执行,我们通常规定满足以下任一条件的对象或者变量为垃圾:
没有被引用的变量或者对象相当于一座没有门的房子,我们永远都无法进入其中,因此不可能在用到它们。无法访问到的对象之间虽然具备连通性,但是仍然无法从外部进入其中,因此也无法再次被利用。满足以上条件的对象或者变量,在程序未来执行过程中绝对不会再次被采用,因此可以放心的当作垃圾回收。
三、垃圾回收垃圾回收机制( 字符串、对象和数组没有固定的大小,所以只有当它们大小已知时才能对它们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都要分配内存才存储这个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便它们能够被再次利用;否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。
四、可达性(Reachability)不同的编程语言采用不同的垃圾回收策略,例如
以上变量称为根,是可达性树的顶层节点。 如果一个变量或则对象,直接或者间接的被根变量应用,则认为这个变量是可达的。 换一个说法,如果一个值能够通过根访问到(例如, 五、可达性举例层次关联:let people = {
boys:{
boys1:{name:'xiaoming'},
boys2:{name:'xiaojun'},
},
girls:{
girls1:{name:'xiaohong'},
girls2:{name:'huahua'},
}};以上代码创建了一个对象,并赋值给了变量
其中, 如果我们在以上代码的后面加上以下代码: people.girls.girls2 = null;people.girls.girls1 = people.boys.boys2; 那么,以上引用层次图将会变成如下形式:
其中, 而如果此时,我们再执行以下代码: people.boys.boys2 = null; 那么引用层次图将变成如下形式: 此时,虽然
相互关联:let people = {
boys:{
boys1:{name:'xiaoming'},
boys2:{name:'xiaojun'},
},
girls:{
girls1:{name:'xiaohong'},
girls2:{name:'huahua'},
}};people.boys.boys2.girlfriend = people.girls.girls1;
//boys2引用girls1people.girls.girls1.boyfriend = people.boys.boys2; //girls1引用boys2以上代码在
此时,如果我们切断 delete people.boys.boys2; 对象之间的关联关系图如下:
显然,并没有不可达的节点出现。 此时,如果我们切断 delete people.girls.girls1; 关系图变为:
此时,虽然 可达孤岛:let people = {
boys:{
boys1:{name:'xiaoming'},
boys2:{name:'xiaojun'},
},
girls:{
girls1:{name:'xiaohong'},
girls2:{name:'huahua'},
}};delete people.boys;delete people.girls;以上代码形成的引用层次图如下:
此时,虽然虚线框内部的对象之间仍然存在相互引用的关系,但是这些对象同样是不可达的,并会被垃圾回收机制删除。这些节点已经和根脱离了关系,变的不可达。 六、垃圾回收算法引用计数所谓引用计-数,顾名思义,就是每次对象被引用时都进行计数,增加引用就加一,删除引用就减一,如果引用数变为0,那么就被认定为垃圾,从而删除对象回收内存。 举个例子: let user = {username:'xiaoming'};
//对象被user变量引用,计数+1
let user2 = user;
//对象被新的变量引用,计数+1
user = null;
//变量不再引用对象,计数-1
user2 = null;
//变量不再引用对象,奇数-1
//此时,对象引用数为0,会被删除虽然看起来引用计数方法非常合理,实际上,采用引用计数方法的内存回收机制存在明显的漏洞。 例如: let boy = {};
let girl = {};
boy.girlfriend = girl;
girl.boyfriend = boy;
boy = null;
girl = null;以上代码在 在 好在 标记清除标记清除( 算法基本过程如下:
举个栗子: 如果我们程序中存在如下图所示的对象引用关系:
我们可以清晰的看到,在整个图片的右侧存在一个“可达孤岛”,从根出发,永远无法到达孤岛。但是垃圾回收器并没有我们这种上帝视角,它们只会根据算法会首先把根节点打上优秀员工标记。
然后从优秀员工出发,找到所有被优秀员工引用的节点,如上图中虚线框中的三个节点。然后把新找到的节点同样打上优秀员工标记。
反复执行查找和标记的过程,直至所有能找到的节点都被成功标记。
最终达到下图所示的效果:
由于在算法执行周期结束之后,右侧的孤岛仍然没有标记,因此会被垃圾回收器任务无法到达这些节点,最终被清除。
七、性能优化垃圾回收是一个规模庞大的工作,尤其在代码量非常大的时候,频繁执行垃圾回收算法会明显拖累程序的执行。 性能优化采取的策略通常包括以下几点: 分代回收
增量收集增量式的思想在性能优化上非常常见,同样可以用于垃圾回收。在变量数目非常大时,一次性遍历所有变量并颁发优秀员工标记显然非常耗时,导致程序在执行过程中存在卡顿。所以,引擎会把垃圾回收工作分成多个子任务,并在程序执行的过程中逐步执行每个小任务,这样就会造成一定的回收延迟,但通常不会造成明显的程序卡顿。 空闲收集
八、总结本文的主要任务是简单的结束垃圾回收的机制、常用的策略和优化的手段,并不是为了让大家深入了解引擎的后台执行原理。 通过本文,你应该了解:
【相关推荐:javascript视频教程、web前端】 以上就是JavaScript隐藏机制之垃圾回收知识总结的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |
