JavaScript中的垃圾收集机制(标记清除和引用计数)

垃圾收集机制

JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。这样我们在编写 JavaScript 代码时就不需在关心内存使用问题了,所需内存分配和已用内存的回收完全实现了自动管理。

这种垃圾收集机制的原理其实非常简单:
找出那些不再使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性的执行这一操作。


局部变量的生命周期:

局部变量只在函数的执行过程中存在。
在这个过程中,首先会为局部变量在栈(或堆)内存上分配相应空间,以便存储他们的值。然后在函数中使用这些变量,直到函数执行结束。此时,局部变量就没有存在的必要了,因此可以释放它们的内存以供将来使用


在垃圾自动收集机制中,最关键的在于如何判断这个变量是否还有存在的必要。也就是判断是否该释放这个变量的内存。因此,垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来回收内存
实现这个功能通常有两个策略:标记清除引用计数

1. 标记清除

标记清除是 JavaScript 中最常用的垃圾收集方式。

当变量进入环境(例如,在函数中声明一个变量)时,将这个变量标记为 “进入环境” 。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为我们在这个环境中可能随时会用到它们。当变量离开环境时,则将其标记为 “离开环境”。

2. 引用计数

另一种不太常见的垃圾收集策略就是引用计数。

引用计数的含义就是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,这个值的引用次数就是 1。如果同一个值又被赋值给另一个变量,则引用次数加 1。相反,如果包含对这个值的引用的变量有取了另一个值,则引用次数减 1。当这个值的引用次数变为 0 时,说明已经没法再访问这个值了,因此可以将其占用的内存回收了。

引用计数策略有一个很严重的问题:循环引用。
如果对象 A 中包含一个指针指向对象 B,而对象 B 中也包含一个指针指向对象 A。那么这两个对象引用次数都是 2,但实际上已经可以回收了。若这种函数被反复多次调用,会导致大量内存得不到回收。

猜你喜欢

转载自blog.csdn.net/TalonZhang/article/details/84594318