前端面试:谈谈 JS 垃圾回收机制

时间:2023-02-22 12:55:45

摘要: 不是每个人都回答的出来...

前端面试:谈谈 JS 垃圾回收机制

最近看到一些面试的回顾,不少有被面试官问到谈谈JS 垃圾回收机制,说实话,面试官会问这个问题,说明他最近看到一些关于 JS 垃圾回收机制的相关的文章,为了 B 格,就会顺带的问问。

最近看到一篇讲 JS 垃圾回收的国外文章,觉得讲得明白,所以就翻译过来了,希望对你们有所帮助。

垃圾回收

JavaScript 中的内存管理是自动执行的,而且是不可见的。我们创建基本类型、对象、函数……所有这些都需要内存。

当不再需要某样东西时会发生什么? JavaScript 引擎是如何发现并清理它?

可达性

JavaScript 中内存管理的主要概念是可达性。

简单地说,“可达性” 值就是那些以某种方式可访问或可用的值,它们被保证存储在内存中。

1. 有一组基本的固有可达值,由于显而易见的原因无法删除。例如:

  • 本地函数的局部变量和参数
  • 当前嵌套调用链上的其他函数的变量和参数
  • 全局变量
  • 还有一些其他的,内部的

这些值称为根。

2. 如果引用或引用链可以从根访问任何其他值,则认为该值是可访问的。

例如,如果局部变量中有对象,并且该对象具有引用另一个对象的属性,则该对象被视为可达性, 它引用的那些也是可以访问的,详细的例子如下。

JavaScript 引擎中有一个后台进程称为垃圾回收器,它监视所有对象,并删除那些不可访问的对象。

一个简单的例子

下面是最简单的例子:

// user 具有对象的引用
let user = {
name: "John"
};

前端面试:谈谈 JS 垃圾回收机制

这里箭头表示一个对象引用。全局变量“user”引用对象 {name:“John”} (为了简洁起见,我们将其命名为John)。John 的 “name” 属性存储一个基本类型,因此它被绘制在对象中。

如果 user 的值被覆盖,则引用丢失:

user = null;

前端面试:谈谈 JS 垃圾回收机制

现在 John 变成不可达的状态,没有办法访问它,没有对它的引用。垃圾回收器将丢弃 John 数据并释放内存。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

两个引用

现在让我们假设我们将引用从 user 复制到 admin:

// user具有对象的引用
let user = {
name: "John"
}; let admin = user;

前端面试:谈谈 JS 垃圾回收机制

现在如果我们做同样的事情:

user = null;

该对象仍然可以通过 admin 全局变量访问,所以它在内存中。如果我们也覆盖admin,那么它可以被释放。

相互关联的对象

现在来看一个更复杂的例子, family 对象:

function marry (man, woman) {
woman.husban = man;
man.wife = woman; return {
father: man,
mother: woman
}
} let family = marry({
name: "John"
}, {
name: "Ann"
})

函数 marry 通过给两个对象彼此提供引用来“联姻”它们,并返回一个包含两个对象的新对象。

产生的内存结构:

前端面试:谈谈 JS 垃圾回收机制

到目前为止,所有对象都是可访问的。

现在让我们删除两个引用:

delete family.father;
delete family.mother.husband;

前端面试:谈谈 JS 垃圾回收机制

仅仅删除这两个引用中的一个是不够的,因为所有对象仍然是可访问的。

但是如果我们把这两个都删除,那么我们可以看到 Jo加粗文字hn 不再有传入的引用:

前端面试:谈谈 JS 垃圾回收机制

输出引用无关紧要。只有传入的对象才能使对象可访问,因此,John 现在是不可访问的,并将从内存中删除所有不可访问的数据。

垃圾回收之后:

前端面试:谈谈 JS 垃圾回收机制

无法访问的数据块

有可能整个相互连接的对象变得不可访问并从内存中删除。

源对象与上面的相同。然后:

family = null;

内存中的图片变成:

前端面试:谈谈 JS 垃圾回收机制

这个例子说明了可达性的概念是多么重要。

很明显,John和Ann仍然链接在一起,都有传入的引用。但这还不够。

“family”对象已经从根上断开了链接,不再有对它的引用,因此下面的整个块变得不可到达,并将被删除。

内部算法

基本的垃圾回收算法称为“标记-清除”,定期执行以下“垃圾回收”步骤:

  • 垃圾回收器获取根并“标记”(记住)它们。
  • 然后它访问并“标记”所有来自它们的引用。
  • 然后它访问标记的对象并标记它们的引用。所有被访问的对象都被记住,以便以后不再访问同一个对象两次。
  • 以此类推,直到有未访问的引用(可以从根访问)为止。
  • 除标记的对象外,所有对象都被删除。

例如,对象结构如下:

前端面试:谈谈 JS 垃圾回收机制

我们可以清楚地看到右边有一个“不可到达的块”。现在让我们看看“标记并清除”垃圾回收器如何处理它。

第一步标记根

前端面试:谈谈 JS 垃圾回收机制

然后标记他们的引用

前端面试:谈谈 JS 垃圾回收机制

以及子孙代的引用:

前端面试:谈谈 JS 垃圾回收机制

现在进程中不能访问的对象被认为是不可访问的,将被删除:

前端面试:谈谈 JS 垃圾回收机制

这就是垃圾收集的工作原理。JavaScript引擎应用了许多优化,使其运行得更快,并且不影响执行。

一些优化:

  • 分代回收——对象分为两组:“新对象”和“旧对象”。许多对象出现,完成它们的工作并迅速结 ,它们很快就会被清理干净。那些活得足够久的对象,会变“老”,并且很少接受检查。
  • 增量回收——如果有很多对象,并且我们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有一定的延迟。因此,引擎试图将垃圾回收分解为多个部分。然后,各个部分分别执行。这需要额外的标记来跟踪变化,这样有很多微小的延迟,而不是很大的延迟。
  • 空闲时间收集——垃圾回收器只在 CPU 空闲时运行,以减少对执行的可能影响。

面试怎么回答

1)问什么是垃圾

一般来说没有被引用的对象就是垃圾,就是要被清除, 有个例外如果几个对象引用形成一个环,互相引用,但根访问不到它们,这几个对象也是垃圾,也要被清除。

2)如何检垃圾

一种算法是标记 标记-清除 算法,还想说出不同的算法可以参考这里

更深入一些的讲解 V8 之旅: 垃圾回收器

还有一种牛逼的答法就是说看我的博客,当然是要自己总结的博客。

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎大家免费试用

前端面试:谈谈 JS 垃圾回收机制

前端面试:谈谈 JS 垃圾回收机制的更多相关文章

  1. 谈谈 JS 垃圾回收机制

    谈谈 JS 垃圾回收机制 JS内存泄漏与垃圾回收机制 https://javascript.info/garbage-collection

  2. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  3. 浅尝js垃圾回收机制

    局部作用域内的变量,在函数执行结束之后就会被js的垃圾回收机制销毁   为什么要销毁局部变量? => 为了释放内存   js垃圾回收机制何时会销毁局部变量 : 如果局部变量无法再得到访问,就会被 ...

  4. 闭包内的微观世界和js垃圾回收机制

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  5. js 垃圾回收机制和引起内存泄漏的操作

    垃圾回收机制 JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记为“离开环境”.标记“离开环境”的就回收内存. 工作流程: ...

  6. 理解闭包的微观世界和JS垃圾回收机制

    function a() { ; function b() { alert(++i); } return b; } var c = a(); c(); 一.闭包的微观世界 如果要更加深入的了解闭包以及 ...

  7. v8垃圾回收和js垃圾回收机制

    垃圾回收器是一把十足的双刃剑.好处是简化程序的内存管理,内存管理无需程序员来操作,由此也减少了长时间运转的程序的内存泄漏.然而无法预期的停顿,影响了交互体验.本文从 V8 (node.js runti ...

  8. 谈谈java垃圾回收机制

    近期看了一些关于垃圾回收机制的文章,总结一下. 垃圾回收器回收程序不在使用的对象占用的内存,也就是对象不可达,比方说对象被置为null. 要回到java的垃圾回收机制,从下面三个方面去回答: 1.哪些 ...

  9. 谈谈JVM垃圾回收机制及垃圾回收算法

    一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理.由于有个垃圾回收机制 ...

随机推荐

  1. yii2创建数据表

    原文地址: http://blog.csdn.net/xiaoyangxiaodong/article/details/45026865

  2. vmware虚拟机 32位Ubuntu 安装matlab_R2012A问题小记

    最近由于学校课程的需要,所以在Ubuntu上捣腾了一下matlab,经历曲折,记录一下,希望能让大家少跳点坑.先分享一个有效的下载链接: http://www.matlab.org.cn/Downlo ...

  3. MATLAB 编程风格指南及注意事项

    MATLAB编程风格指南Richard Johnson 著Genial 译MATLAB 编程风格指南Richard JohnsonVersion 1.5,Oct. 2002版权: Datatool 所 ...

  4. 十一、Android学习笔记_AsyncQueryHandler的应用

    研究AsyncQueryHandler这个类的时候遇到了几个重要的不清楚的知识点 1. Handler与Thread,Looper的关系 2. HandlerThread是干什么用的 3. Threa ...

  5. (转)select 1 from ... sql语句中的1代表什么意思? .

    select  1 from ..., sql语句中的1代表什么意思?查出来是个什么结果?         select 1 from table;与select anycol(目的表集合中的任意一行 ...

  6. hrbustoj 1494(原题UVA 315 Network) 解题报告 tarjan求割点

    主要思路:使用tarjan选取一个根节点建立一个棵搜索树,判断一个点是割点的充分必要条件是,对于一个节点u如果他的孩子节点v的low值大于等于u的出生日期dfn值,进行下一步判断,如果u是我们选的根节 ...

  7. iOS之 重绘机制

    最近在看Core Animation , 今天来谈谈CALayer 和 UIView 中的重绘的一些认识: 我们都知道UIView里面有个成员layer,利用这个这个layer我们可以设置一些圆角,阴 ...

  8. .Net ABP 框架 service 无法访问

    最近在看ABP框架,按照文档写好service后,怎么也访问不到,后来发现,忘记把service类设置为public的了! 不写public ABP框架就不能将这个service映射为controll ...

  9. vscode断点调试工程化服务端文件

    一.创建express应用我们使用express-generator创建一个新的express应用.1.全局安装express-generator // 安装 sudo npm install exp ...

  10. 〖Android〗从Android Studio转为Eclipse开发项目运行程序闪退的解决方法

    很久没有撸Android App开发了- 最近把一个月前通过反编译.二次修改的Android SSHD项目进行简单修改一下: 突然发现迁移项目时,报了一个错误,同时还出现了闪退情况: - ::): t ...