在 JavaScript 中,所有创建的对象、函数、原始值都会占用内存,如果有一些东西在接下来不会再被使用,那么它就会被清理掉。这一切都是自动实现的,开发者不需要刻意的去清理某个占用内存的东西。了解垃圾回收的运行机制,可能对我们快速编写一个 JavaScript 应用没什么帮助,但它非常有助于我们理解 JavaScript 代码执行的机制,对于如何编写更高性能、更安全的应用也会很有帮助。

可达性

可达性(Reachability)是 JavaScript 内存管理中非常重要的概念。

“可达”值是那些以某种方式可访问或可用的值,它们一定是存储在内存中的。

假设:有一个变量在整个代码的起始处声明了,同时在代码最后用到了,那么这个变量就始终是可达的,它会始终存在内存中,以保证在代码的最后也能用它。

再假设:有一个变量是在某个函数里面声明的,对该变量的相关操作也只在这个函数中进行,那么这个变量只会在函数执行的时候创建、占用内存,当函数执行结束后,该变量就会被当成“垃圾”即使清理掉,从而释放它所占用的内存。

执行这一系列操作的是一个称作“垃圾回收器”的东西,它始终在 JavaScript 引擎的后台运行。它的任务就是监控所有对象的状态,及时发现 不可达 的对象并清理掉它们。

内部执行

垃圾回收的基本算法被称为“标记-清理”(mark-and-sweep)。
垃圾回收器会 定期 执行以下操作:

  1. 从起点出发,遍历所有对象,在遍历的同时做上标记
  2. 清理所有没有被标记的对象

例如,我们有如下结构的对象:
image.png
垃圾回收器可以遍历左边的所有对象,它们的状态就都是“可达”的;右边的三个对象因为无法从起点遍历到,状态就是“不可达”,就会被清理掉:
image.png

总结

  • 垃圾回收是自动完成的,我们无法强制执行或阻止执行。
  • 可达 = 可访问 = 存在内存中
  • 引用与可访问并不同:一组相互引用的对象可能整体都不可访问