zl程序教程

您现在的位置是:首页 >  其他

当前栏目

红宝书 ? 4.3 垃圾回收

2023-02-25 18:16:16 时间

垃圾回收

JavaScript是使用垃圾回收的语言,也就是执行环境负责在代码执行时管理内存。

基本思路 垃圾回收♻️程序每隔一段时间就会运行,找到不被使用的变量,然后释放它的内存。但是,哪个变量不被使用,是不可判定的问题,算法也解决不了。因此,垃圾回收程序会跟踪记录变量的使用状态,如何标记?,在浏览器的发展史上用到过两种标记策略。如下

【标记清理】*

【1】 变量进入上下文(函数内部声明一个变量时),这个变量会被加入上下文的标记?。

加标签的方式例如:

  • 进入上下文时,反转某一位
  • 维护“在上下文”和“不在上下文”的变量
  • 把变量从一个列表移到另一个列表

标记过程的实现并不重要,关键是策略。

【2】 垃圾回收程序运行的时候,会标记?内存中的所有变量。

【3】 去掉上下文中使用和引用的变量的标记?

【4】 仍有标记?的就是待销毁的变量

【5】 垃圾回收♻️程序做一次内存清理,清理掉这些变量并回收内存

了解即可:

各种浏览器在自己的JavaScript实现中采用标记清理,只是在运行回收的频率上有所差异。

【引用计数】

不常用

【思路】:记录每个值的引用次数

例如声明变量a,let a ={"name":"test"}此时这个值{"name":"test"}的引用数为1,

把a的这个引用值赋值给blet b = a,那么值得引用数+1。

类似的,当把这个引用值覆盖调,引用数-1,即b.name="change"

当一个值得引用数为0,这个值就可以安全回收了。

【最后】垃圾回收♻️程序下次运行会释放引用数为0的值得内存

【存在的问题】

     function problerm(){
         let obja = new Object()
         let objb = new Object()
         obja.cona = objb
         objb.conb = obja
     }

两个对象间相互引用,也就是引用数都是2。在引用计数策略下,两个对象在函数结束后还会存在,引用计数不会变成0。调用多次会导致内存永远不会释放。

【性能】

【垃圾回收的时间调度】

垃圾回收程序会周期性运行,如果内存中分配了很多变量,则可能造成性能损失。尤其是移动设备,其内存有限,垃圾回收会拖慢渲染的速度和帧率。我们开发并不知道什么时候会收集垃圾,因此写代码时做到,让它尽快结束。

【何时运行】

垃圾回收程序会基于对JavaScript运行时环境的探测来决定什么时候运行,不同探测引擎机制不同,但基本都是根据已分配对象的大小和数量判断的。

在某些浏览器中,可以主动触发垃圾回收机制但不推荐。如 IE window.CollectGarbage(),Opera的 window.opera.collect()

【内存管理】

开发者通常不需要关心内存。 JavaScript运行在一个内存管理与垃圾回收都很特殊的环境,分配内存排序:桌面软件>浏览器>移动浏览器。这是出于安全考虑,避免大量JavaScript运行耗尽系统内存导致操作系统崩溃。 这个内存限制不仅影响变量分配,也影响调用栈以及能够同时在一个线程中执行的语句数量