关于 JS 的垃圾回收机制

204 阅读2分钟

1、什么是垃圾

  • 不再被需要的,就是垃圾
    • 全局变量都不是垃圾,有可能还会被使用到,如var a = { name: 'xxx' }
    • 全局变量 = null,则原来的对象就变成了垃圾,如a = null
    • 局部变量在调用这个函数以后,就变成了垃圾,因为不会再用到这个变量。就算再次调用该函数,使用到的变量也不是原来的变量了
      •    function fn(){
               var b = 1
               console.log(b)
           } 
           fn()
        
  • 如果存在双引用
    • 删除其中一个引用,该对象还是存在的
    • 如:
var a = { name: 'xxx' }
var b = a
a = null 
  • 如果是环引用呢?
    • 如:
    • 如果引用 father 的变量都松开了手,那么 father 这个对象就变成了垃圾
    • 如果删除了 father 和 mother 与外界的联系 family,那么 father 和 mother 这两个对象也会变成垃圾

2、关于垃圾回收算法

  1. 标记清除算法(Mark-Swipe):从全局作用域开始,把所有用到的变量都标记一下,如果标记过的变量还有其他引用到的变量,就再次进行标记,一直标记到没有新的引用的对象,标记结束。然后把其他没有标记的对象全部清除掉。

    • 图示:
    • 标记算法存在的缺点:由于 JS 是单线程的,当对象数量过多时,就会耗费过多的时间来加载 JS。
    • 改进方法:分代回收(分为新生代和老一代)、分批遍历、空闲时间回收
  2. 引用计数算法:本质是跟踪记录每个值被引用的次数。其执行机制如下:

    • 当声明一个变量并将一个引用类型值赋值给该变量时,这个值的引用次数为1;
    • 若同一个值(变量)又被赋值给另一个变量,则该值的引用次数加1;
    • 但是如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1;
    • 当这个值的引用次数为0时,则无法再访问这个值,就可回收其占用的内存空间。
  3. 其他算法还包括:

  • 分代回收
  • Scavenge 算法
  • 标记-紧缩算法
  • ...
  • 这些算法暂时还并不是很了解,之后随着学习的深入,相信可以慢慢的更好的理解