基本类型存放在栈中,引用类型存放在堆中。JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。
垃圾回收策略
所有垃圾回收器都需要做的任务
标记空间中活动(存活)对象和非活动(非存活)对象
回收或者重用被非活动对象占据的内存
内存整理,防止内存碎片的出现
什么是垃圾对象?
一般来说没有被引用的对象就是垃圾,就是要被清除。从根开始遍历对象。
例外
如果几个对象引用形成一个环,互相引用,但根访问不到它们,这几个对象也是垃圾,也要被清除。
什么是根对象和存活对象
根对象
有一组基本的固有可达值,由于显而易见的原因无法删除
- 全局变量 window全局对象、DOM文档树根对象等
- …
存活对象
如果引用或引用链可以从根访问任何其他值,则认为该值是可访问的
V8引擎回收 分代回收法
将堆分为新生代和老生代。
新生代中存放的是生存时间短的对象,老生代中存放的生存时间久的对象。
新生代垃圾回收器 scavenge复制算法
将堆内存分为两部分,一个是使用区,处于使用状态的空间;另一个是空闲区,处于空闲状态的空间。
新加入的对象会存放到使用区,当使用区快被写满时,就需要进行垃圾清理操作。
新生代垃圾回收器会对使用区的活动对象对象做标记,标记完成之后将使用区的活动对象复制到空闲区。解决了内存散落分块的问题。
将使用区的非活动对象占用的空间清理掉。最后进行角色互换,原来的使用区变成新的空闲区,原来的空闲区变成新的使用区。
移动到老生代的对象
- 如果一个对象多次复制后仍然存活,将被认为时生命周期较长的对象,随后被移动到老生代中。
- 复制一个对象到空闲区时,占用空闲区空间超过了25%,这个对象会被直接晋升到老生代空间中。原因是原来的空闲区会变成新的使用区,继续进行对象内存的分配,若占比过高,新对象的可用空间太少。
新生代优化 并行回收
全停顿问题
JavaScript是单线程语言,运行在主线程上,进行垃圾回收时会阻塞JavaScript脚本的执行,需要等待垃圾回收完毕后再恢复脚本执行。
如果一次GC的时间过长,可能造成页面卡顿现象。
并行回收机制
垃圾回收器在主线程上执行的过程中,开启多个辅助线程,同时执行同样的回收工作。
老生代垃圾回收
使用scavenge方式存在的问题
1.存活对象较多,频繁复制存活对象效率将降低
2.浪费一半空间
主要采用标记-清除法,在内存分配不足时,采用标记-整理法
老年代垃圾回收期采用的算法
1. 首先使用标记-清除完成垃圾空间的回收;
2. 采用标记-整理进行空间优化;
3. 采用优化-增量标记与惰性清理进行效率优化;
标记-清除 与 标记-整理 算法
scavenge只复制活着的对象,而标记-清除只清除死了的对象。
活对象在新生代中只占较少部分,死对象在老生代中只占较少部分,这就是两种回收方式都能高效处理的原因。
缺点
内存碎片太多。如果出现需要分配一个大内存的情况,由于剩余的碎片空间不足以完成此次分配,就会提前触发垃圾回收,而这次回收是不必要的。
-> 标记-整理算法 标记完存活对象后,将存活对象向内存空间的一端移动,移动完成后,清除掉边界外的所有内存
优化-增量标记与惰性清理
增量标记
如果有很多对象,并且我们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有一定的延迟。因此,引擎试图将垃圾回收分解为多个部分。然后,各个部分分别执行。
V8对老生代垃圾回收器进行了优化,从全停顿标记切换到增量标记。
将一次垃圾回收变成一小段一小段GC垃圾回收
如果采用非黑即白(存活和死亡)的标记策略,那在垃圾回收器执行了一段增量回收后,暂停后启用主线程去执行了应用程序中的一段 JavaScript 代码,随后当垃圾回收器再次被启动,这时候内存中黑白色都有,我们无法得知下一步走到哪里了
惰性清理
增量标记完成后,惰性清理就开始了。当增量标记完成后,假如当前的可用内存足以让我们快速的执行代码,其实我们是没必要立即清理内存的,可以将清理过程稍微延迟一下,让 JavaScript 脚本代码先执行,也无需一次性清理完所有非活动对象内存,可以按需逐一进行清理直到所有的非活动对象内存都清理完毕,后面再接着执行增量标记
三色标记法 暂停和恢复
三色标记法的 mark 操作可以渐进执行的而不需每次都扫描整个内存空间,可以很好的配合增量回收进行暂停恢复的一些操作,从而减少 全停顿 的时间
- 白色:未被标记的对象
- 灰色:自身被标记,该对象的引用对象未被标记
- 黑色:自身和该对象的引用对象(箭头指的对象)都被标记
从一组根对象开始,先将这组根对象标记为灰色并推入到标记工作表中,当回收器从标记工作表中弹出对象并访问它的引用对象时,将其自身由灰色转变成黑色,并将自身的下一个引用对象转为灰色
就这样一直往下走,直到没有可标记灰色的对象时,也就是无可达的对象了,那么剩下的所有白色对象都是无法到达的,即等待回收。
当前内存中有没有灰色节点来判断整个标记是否完成,如没有灰色节点,直接进入清理阶段,如还有灰色标记,恢复时直接从灰色的节点开始继续执行就可以
写屏障
一次完整的GC标记分块暂停后,执行任务程序,修改了对象的引用关系。
假设在第一次增量分段中全部将ABC标记为黑色,然后执行JavaScript脚本,将B->D,开始执行第二次增量分段。
新对象D是初始的白色,但是此时没有灰色对象了,也就是全部标记完成需要开始清理了,D将会在清理阶段被回收。这是不对的。
V8引入写屏障机制,一旦有黑色对象引用白色对象,该机制就将引用的白色对象变为灰色。
并发回收
- 并行回收会阻塞主线程
- 增量标记增加了总暂停时间、降低应用程序吞吐量
主线程在执行 JavaScript 的过程中,辅助线程能够在后台完成执行垃圾回收的操作
【推荐学习:javascript高级教程】
以上是深入浅析JS中的垃圾回收机制的详细内容。更多信息请关注PHP中文网其他相关文章!

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

Atom编辑器mac版下载
最流行的的开源编辑器

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)