javaScript垃圾回收机制(垃圾数据是如何自动回收的)

一.javaScript数据类型存储

若想了解javaScript的垃圾数据是如何自动回收的,首先我们应该先简单知道一下关于javascript的数据垃圾数据是如何存储的(JavaScript的内存机制)。
1.JavaScript的数据类型

JavaScript是一种弱类型的、动态的语言

● 弱类型,意味着你不需要告诉JavaScript引擎这个或那个变量是什么数据类型,JavaScript引擎在运行代码的时候自己会计算出来。

● 动态,意味着你可以使用同一个变量保存不同类型的数据。

JavaScript中的数据类型一种有8种(原始类型和引用类型):
Number、String、Boolean、Null、 Undefined、Symbol(ES6),BigInt(ES11)Object(引用类型)

2.内存空间

从图中可以看出, 在JavaScript的执行过程中, 主要有三种类型内存空间,分别是代码空间、栈空间和堆空间

原始类型的数据是存放在栈中,引用类型的数据是存放在堆中的。堆中的数据是通过引用和变量关联起来的。也就是说,JavaScript的变量是没有数据类型的,值才有数据类型,变量可以随时持有任何类型的数据。

二.垃圾数据是如何自动回收的?

1.栈中的垃圾数据

示例:

bash 复制代码
function foo(){
    var a = 1
    var b = {name:"孙悟空"}
    function showName(){
      var c = 2
      var d = {name:"天蓬元帅"}
    }
    showName()
}
foo()

当执行到showName函数时,原始类型(c)的数据被分配到栈中,引用类型(d)的数据会被分配到堆中。JavaScript引擎会创建showName函数的执行上下文,并将showName函数的执行上下文压入到调用栈中,最终执行到showName函数时,与此同时,还有一个记录当前执行状态的指针称为ESP),指向调用栈中showName函数的执行上下文,表示当前正在执行showName函数。

接着,当showName函数执行完成之后,函数执行流程就进入了foo函数,那这时就需要销毁showName函数的执行上下文了。ESP 这时候就帮上忙了,JavaScript会将ESP下移到foo函数的执行上下文,这个下移操作 就是销毁showName函数执行上下文的过程。

所以说,当一个函数执行结束之后,JavaScript引擎会通过向下移动ESP来销毁该函数保存在栈中的执行上下文。

2.堆中的数据是如何回收的?

通过上面的讲解,当上面那段代码的foo函数执行结束之后,ESP 应该是指向全局执行上下文的,那这样的话,showName函数和foo函数的执行上下文就处于无效状态了,不过保存在堆中的两个对象(b,d)依然占用着空间。
要回收堆中的垃圾数据,就需要用到JavaScript中的垃圾回收器了
(a).垃圾回收器分类

V8中会把堆分为新生代老生代 两个区域,新生代中存放的是生存时间短的对象,老生代中存放的生存时间久的对象。

●副垃圾回收器,主要负责新生代的垃圾回收。

● 主垃圾回收器,主要负责老生代的垃圾回收。
(b).垃圾回收器的工作流程:

V8把堆分成两个区域------新生代和老生代,并分别使用两个不同的垃圾回收器。其实不论什么类型的垃圾回收器,它们都有一套共同的执行流程。
第一步是标记空间中活动对象和非活动对象。所谓活动对象就是还在使用的对象,非活动对象就是可以进行垃圾回收的对象。

第二步是回收非活动对象所占据的内存。其实就是在所有的标记完成之后,统一清理内存中所有被标记为可回收的对象。

第三步 是做内存整理。一般来说,频繁回收对象后,内存中就会存在大量不连续空间,我们把这些不连续的内存空间称为内存碎片。当内存中出现了大量的内存碎片之后,如果需要分配较大连续内存的时候,就有可能出现内存不足的情况
(c).全停顿

V8是使用副垃圾回收器和主垃圾回收器处理垃圾回收的,不过由于JavaScript是运行在主线程之上的,一旦执行垃圾回收算法,都需要将正在执行的JavaScript脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿(Stop-The-World)

在V8新生代的垃圾回收中,因其空间较小,且存活对象较少,所以全停顿的影响不大,但老生代就不一样了。如果在执行垃圾回收的过程中,占用主线程时间过久,比如页面正在执行一个JavaScript动画,因为垃圾回收器在工作,就会导致这个动画在这段时间内无法执行的,这将会造成页面的卡顿现象。

(d).增量标记

使用增量标记算法,可以把一个完整的垃圾回收任务拆分为很多小的任务,这些小的任务执行时间比较短,可以穿插在其他的JavaScript任务中间执行,这样当执行上述动画效果时,就不会让用户因为垃圾回收任务而感受到页面的卡顿了。

为了降低老生代的垃圾回收而造成的卡顿,V8将标记过程分为一个个的子标记过程,同时让垃圾回收标记和JavaScript应用逻辑交替进行,直到标记阶段完成,我们把这个算法称为增量标记(Incremental Marking)算法

相关推荐
&岁月不待人&12 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove16 分钟前
G1垃圾回收器日志详解
java·开发语言
无尽的大道24 分钟前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
爱吃生蚝的于勒27 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
binishuaio36 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE38 分钟前
【Java SE】StringBuffer
java·开发语言
就是有点傻42 分钟前
WPF中的依赖属性
开发语言·wpf
洋2401 小时前
C语言常用标准库函数
c语言·开发语言
进击的六角龙1 小时前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
wrx繁星点点1 小时前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式