垃圾回收算法(v8)
可达性
: 从根节点登程,遍历所有的对象,能够遍历到的对象,就是 可达的
根节点蕴含:
- 全局变量
window
- 文档
DOM
树 - 寄存在栈上的变量
例
let dog.a = new Array(1)
如果此时,将另外一个对象赋给 a
dog.a = new Object()
那么从根节点 栈 dog
一步一步遍历,发现 堆 Array
是 不可达的,那么它就要被回收掉。
此时会引出一个概念:内存碎片
内存碎片就是不可达的对象被回收后,内存中会存在大量的不间断空间
还有一个问题:浏览器在进行垃圾回收的时候,会暂停 JS 脚本,可能会导致页面卡顿
所以新引擎对其进行了优化
分代收集
浏览器将数据分为两种:短暂对象 和长期对象
生命周期很长的对象,比方全局的 window/DOM
等属于短暂对象
存活工夫短,比方函数外部变量,块级作用域变量等属于长期对象
与之对应的垃圾回收器别离是 主垃圾回收器 和副垃圾回收器
主垃圾回收器
使用优化版 可达性
回收算法 标记 - 革除
,在遍历过程中, 可达的 对象进行标记,那么最初没有标记的就判断为垃圾数据。
标记:一个对象拜访一次
屡次回收也会呈现 内存碎片 ,须要进行 内存整理
副垃圾回收器
负责长期对象的垃圾回收,通常只反对 1~8M 的容量
分为两个区域: 对象区域 和闲暇区域
新退出的对象都被放入对象区域,等对象区域快满的时候,会执行一次垃圾清理
清理过程:
- 先给对象区域所有对象进行标记
- 把标记的可达的对象复制到闲暇区域,并且将它们有序的排列一边
- 对象区域与闲暇区域对调
在这个模式下,就不会呈现内存碎片问题
增量回收
为了解决优化过程中页面提早问题的优化
将垃圾回收工作分成更小的块,每次解决一部分,屡次解决,这样就会防止长时间的进展
闲时收集
也是一种优化,垃圾收集器只会在 CPU 闲暇时尝试运行,以缩小可能对代码执行的影响
内存透露
用不到的变量,不能被垃圾回收机制回收,仍然占据着内存空间
常见场景:
- 监听在
window/body
事件没有解绑 - Vue 中的
$store
,watch
之后没有unwatch
- 相互援用
- 定时器
- 滥用闭包
优化:
- 弱援用
weakMap/weakset
- 数组复用:arr.length = 0
- 对象复用:t = null
weakMap 和 weakset
弱援用,特点:不能确保其援用的对象不会被垃圾回收器回收
var obj1 = new Object() // 强援用
var obj2 = new WeakMap() // 弱援用
如果两个对象什么都不做,那么 obj2
就会被回收掉,而 obj1
要设置 obj1=null
才会被回收