什么是垃圾?
- 1.没有被引用的对象或变量
- 2.无法访问到的对象
为啥需要垃圾回收?
- 程序和人一样,生活时间长了会产生垃圾,程序在运行过程中也会产生垃圾,垃圾积攒过多后,会导致程序运行速度变慢。
- 在JavaScript中的字符串、对象、数组等数据的内存是不固定的,只有真正使用的时候才会动态分配内存。
- 这些数据所占的内存在不使用时,需要进行释放,以便再次使用,否则在可用内存耗尽造成程序崩溃。
什么是垃圾回收?
垃圾回收机制也称Garbage Collection简称GC。在JavaScript中拥有自动的垃圾回收机制,通过一些回收算法,找出不再使用引用的变量或属性,由JS引擎按照固定时间间隔周期性的释放其所占的内存空间。
垃圾回收策略
JavaScript 中主要的内存管理概念是可达性。大概意思是以某种方式可以访问到或者可以使用的值,它们就是需要保存在内存中,无法访问,也无法使用的值,则需要被垃圾回收机制回收。
有一组基本的固有可达值,由于显而易见的原因无法删除。例如:
- 本地函数的局部变量和参数
- 当前嵌套调用链上的其他函数的变量和参数
- 全局变量
这些值称为根
//user 具有对象的引用
let user = { //user的‘name’属性存储一个基本类型,因此它被绘制在对象当中。
name:'mark'
}
user = null //user的值被覆盖,则引用丢失;此时user中的'mark'为不可达状态,没有办法访问它,引用它
// 垃圾回收器将丢弃mark数据并释放内存
垃圾回收过程是不实时进行的,因为JavaScript是一门单线程的语言,每次执行垃圾回收,会使程序应用逻辑暂停,执行完垃圾后回收在执行应用逻辑,这种行为称为全停顿,所以一般垃圾回收会在cpu闲时进行。
如何通过某种方式找到所谓的垃圾,是垃圾回收的重点,这边常见的两种方法为:引用计数算法和标记清除算法;
引用计数策略
引用计数算法 :机制就是跟踪某一个值得引用次数,当声明一个变量并且将一个引用类型赋值给变量得时候引用次数加1,当这个变量指向其他一个时引用次数减1,当为0时出发回收机制进行回收。
let cat = {
name: "小白",
age: 20
}; //此时该对象的引用计数标记为1(a 引用)
let dog = cat; //此时对象的引用计数标记为2(a、b 引用)
cat = null; //此时对象的引用计数标记为1((b 引用))
dog = null; //此时对象的引用计数标记为0(无变量引用)
... //等待GC 回收此对象
标记清除
标记清除算法:大部分浏览器使用这种垃圾回收,当变量进入执行环境(声明变量)的时候,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,将其再度标记,随之进行删除。
大概过程
- 垃圾收集器在运行时会给内存中所有的变量都加上一个标记,假设内存中所有的对象全部是垃圾,全部标记为0
- 然后从各个根对象开始遍历,把不是垃圾的节点改成1
- 清理所有标记为0的垃圾,销毁并回收它们所占用的内存空间
- 最后把所有内存中对象标记修改为0,等待下一轮的垃圾回收