JS的垃圾回收机制

115 阅读3分钟

JavaScript 的垃圾回收机制是一种自动管理内存的机制,它负责在程序运行过程中检测并回收不再使用的内存,以释放资源并避免内存泄漏。

  1. 标记-清除算法(Mark and Sweep)
    • JavaScript 中最常见的垃圾回收算法是标记-清除算法。
    • 这个算法分为两个阶段:标记阶段和清除阶段。
    • 在标记阶段,垃圾回收器会从根对象(通常是全局对象)开始,标记所有从根对象可达的对象,即所有仍然被引用的对象。
    • 在清除阶段,垃圾回收器会遍历堆内存,清除所有未被标记的对象,即所有不再被引用的对象,释放它们所占用的内存空间。
  2. 引用计数算法(Reference Counting)
    • 引用计数算法是另一种垃圾回收算法,它通过记录每个对象被引用的次数来决定是否回收该对象。
    • 当一个对象被引用时,它的引用计数加一;当一个对象的引用失效时,它的引用计数减一。
    • 当一个对象的引用计数变为零时,说明该对象不再被引用,可以被回收。

JavaScript 主要使用标记-清除算法来进行垃圾回收,因为引用计数算法无法处理循环引用的情况,容易导致内存泄漏。标记-清除算法则可以准确地识别和回收不再使用的对象,保证内存的有效利用。 除了自动的垃圾回收机制外,开发者也可以手动释放内存,通常通过将不再使用的变量或对象赋值为 null 来告知垃圾回收器可以回收这些对象所占用的内存。这种做法可以加速内存的释放,但一般情况下并不需要手动干预垃圾回收机制,因为现代浏览器的垃圾回收器已经相当高效。

为什么引用计数法无法处理循环引用的问题呢???

引用计数算法无法处理循环引用的情况主要是因为它依赖于引用计数来确定对象是否可回收,而循环引用会导致对象之间形成了闭环,使得它们的引用计数永远不会变为零,即使它们已经不再被外部引用。这会导致循环引用的对象始终无法被垃圾回收器回收,从而产生内存泄漏。 举个例子,假设有两个对象A和B,它们分别互相引用对方,形成了循环引用。此时,引用计数算法会发现A和B的引用计数始终不会为零,因为它们相互引用对方,即使程序不再使用这两个对象,它们的引用计数也不会减少。因此,这种情况下,引用计数算法无法准确地确定哪些对象可以被回收,从而导致内存泄漏。 为了解决循环引用导致的内存泄漏问题,现代的垃圾回收算法通常采用标记-清除算法等方式,能够通过对象之间的可达性来判断对象是否可回收,从而避免了引用计数算法的这一缺陷。