目录
垃圾回收
可触及(Reachability)
一个简单例子
两个引用
相互引用的对象
孤岛(Unreachable island)
内部算法
总结
首页 web前端 js教程 浅谈一下js的垃圾回收的内容

浅谈一下js的垃圾回收的内容

Jul 16, 2018 am 09:42 AM
javascript 垃圾回收

这篇文章主要介绍了关于js的垃圾回收机制,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

垃圾回收

内存管理于我们来说是自动的、不可见的。我们创建的原始类型、对象、函数等等,都会占用内存。

当它们不被需要之后会发生什么?JavaScript 引擎要如何发现并清除他们?

可触及(Reachability)

JavaScript 内存管理的关键概念是可触及(Reachability)

简单来说,“可触及”的值就是可访问的,可用的,他们被安全储存在内存。

  1. 以下是一些必定“可触及”的值,不管出于任何原因,都不能删除:

  • 当前函数的局部变量和参数。

  • 当前调用链(current chain of nested calls)中所有函数的局部变量和参数。

  • 全局变量。

  • (以及其他内部变量)

这些值都称为 *roots*。
登录后复制
  1. 其他值是否可触及视乎它是否被 root 及其引用链引用。

    假设有一个对象存在于局部变量,它的值引用了另一个对象,如果这个对象是可触及的,则它引用的对象也是可触及的,后面会有详细例子。

JavaScript 引擎有一个 垃圾回收) 后台进程。它监控着所有对象,当对象不可触及时会将其删除。

一个简单例子

// user has a reference to the object
let user = {
  name: "John"
};
登录后复制

2566786521-5b4b1e03a7eb8_articlex[1].png

箭头代表的是对象引用。全局变量 "user" 引用了对象{name: "John"}(简称此对象为 John)。John 的 "name" 属性储存的是一个原始值,所以无其他引用。

如果覆盖 user,对 John 的引用就丢失了:

user = null;
登录后复制
登录后复制

155327879-5b4b1e039f60c_articlex[1].png

现在 John 变得不可触及,垃圾回收机制会将其删除并释放内存。

两个引用

如果我们从 user 复制引用到 admin

// user has a reference to the object
let user = {
  name: "John"
};

*!*
let admin = user;
*/!*
登录后复制

1546865928-5b4b1e038fe5e_articlex[1].png

如果重复一次这个操作:

user = null;
登录后复制
登录后复制

……这个对象是依然可以通过 admin 访问的,所以它依然存在于内存。如果我们把 admin 也覆盖为 null,那它就会被删除了。

相互引用的对象

这个例子比较复杂:

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  }
}

let family = marry({
  name: "John"
}, {
  name: "Ann"
});
登录后复制

marry 函数让两个参数对象互相引用,返回一个包含两者的新对象,结构如下:

1941061787-5b4b1e0308cd3_articlex[1].png

暂时所有对象都是可触及的,但我们现在决定移除两个引用:

delete family.father;
delete family.mother.husband;
登录后复制

1604544661-5b4b1e030276c_articlex[1].png

只删除一个引用不会有什么影响,但是两个引用同时删除,我们可以看到 John 已经不被任何对象引用了:

4016353222-5b4b1e030b7a0_articlex[1].png

即使 John 还在引用别人,但是他不被别人引用,所以 John 现在已经是不可触及的了,它的存在将会被移除。

垃圾回收后:

2369010816-5b4b1e02ecc22_articlex[1].png

孤岛(Unreachable island)

也可能有一大堆互相引用的对象整块(像个孤岛)都不可触及了。

对上面的对象进行操作:

family = null;
登录后复制

内存中的情况如下:

317280959-5b4b1e02da6a3_articlex[1].png

这个例子展示了“可触及”这个概念的重要性。

尽管 John 和 Ann 互相依赖,但这仍不足够。

"family" 对象整个已经切断了与 root 的连接,没有任何东西引用到这里,所以这个孤岛遥不可及,只能等待被删除。

内部算法

基础的垃圾回收算法被称为“标记-清除算法”("mark-and-sweep"):

  • 垃圾回收器获取并标记 root。

  • 然后访问并标记来自他们的所有引用。

  • 访问被标记的对象,标记他们的引用。所有被访问过的对象都会被记录,以后将不会重复访问同一对象。

  • ……直到只剩下未访问的引用。

  • 所有未被标记的对象都会被移除。

假设对象结构如下:

862819114-5b4b1e0218952_articlex[1].png

我们清晰地看到右边的“孤岛”。现在使用“标记-清除”的方法处理他。

第一步,标记 root:

3725254996-5b4b1e0218f2b_articlex[1].png

然后标记他们的引用:

3567439851-5b4b1e022afb7_articlex[1].png

……标记他们引用的引用:

464038720-5b4b1e0226abc_articlex[1].png

现在没有被访问过的对象会被认为是不可触及,他们将会被删除:

2993400725-5b4b1e022dacc_articlex[1].png

这就是垃圾回收的工作原理。

JavaScript 引擎在不影响执行的情况下做了很多优化,使这个过程更垃圾回收效率更高:

  • 分代收集 -- 对象会被分为“新生代”和“老生代”。很多对象完成任务后很快就不再需要了,所以对于他们的清理可以很频繁。而在清理中留下的称为“老生代”一员。

  • 增量收集 -- 如果对象很多,很难一次标记完所有对象,这个过程甚至对程序执行产生了明显的延迟。所以引擎会尝试把这个操作分割成多份,每次执行一份。这样做要记录额外的数据,但是可以有效降低延迟对用户体验的影响。

  • 闲时收集 -- 垃圾回收器尽量只在 CPU 空闲时运行,减少对程序执行的影响。

除此以外还有很多对垃圾回收的优化,在此就不详细说了,各个引擎有自己的调整和技术,而且这个东西一直随着引擎的更新换代在改变,如果不是有实在的需求,不值得挖太深。不过如果你真的对此有浓厚的兴趣,下面会为你提供一些拓展链接。

总结

重点:

  • 垃圾回收自动进行,我们不能强制进行或阻止他。

  • 可触及的对象会被保留在内存中。

  • 被引用不一定是可触及的(从 root):相互引用的对象可能整块都是不可触及的。

现代引擎实现了加强版的垃圾回收算法,《The Garbage Collection Handbook: The Art of Automatic Memory Management》(R. Jones 等)一书中提及了他们。

如果你熟悉底层编程,可以阅读 A tour of V8: Garbage Collection 了解更多关于 V8 垃圾回收的细节。

V8 blog 也会经常发布一些关于内存管理的文章。学习垃圾回收算法最好还是先学习 V8 的实现,阅读 Vyacheslav Egorov(V8 工程师之一)的博客。我说 V8 是因为在互联网上关于 V8 的文章比较多。对于其他引擎,很多实现都是相似的,但是垃圾回收算法上区别不少。

对引擎的深入理解在做底层优化的时候很有帮助。在你熟悉一门语言之后,这是一个明智的研究方向。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

如何通过js判断页面在pc端打开还是移动端打开

对JS中的prototype的详解

以上是浅谈一下js的垃圾回收的内容的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

Java 函数中内存管理技术与安全性的关系是什么? Java 函数中内存管理技术与安全性的关系是什么? May 02, 2024 pm 01:06 PM

Java中的内存管理涉及自动内存管理,使用垃圾回收和引用计数来分配、使用和回收内存。有效的内存管理对于安全性至关重要,因为它可以防止缓冲区溢出、野指针和内存泄漏,从而提高程序的安全性。例如,通过正确释放不再需要的对象,可以避免内存泄漏,从而提高程序性能并防止崩溃。

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

如何在JavaScript中获取HTTP状态码的简单方法 如何在JavaScript中获取HTTP状态码的简单方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务

如何使用WebSocket和JavaScript实现在线协作编辑器 如何使用WebSocket和JavaScript实现在线协作编辑器 Dec 17, 2023 pm 01:37 PM

实时协作编辑器已经成为现代web开发的标配,特别是在各种团队协作、在线文档编辑和任务管理的场景下,基于WebSocket的实时通信技术可以提高团队成员之间的沟通效率和协作效果。本文将介绍如何使用WebSocket和JavaScript构建一个简单的在线协作编辑器,帮助读者更好地理解WebSocket的原理和使用方法。理解WebSocket的基本原理WebSo

See all articles