垃圾回收算法(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
才会被回收
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。