记录--JS 的垃圾回收机制

news2024/9/19 10:46:41

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言

垃圾回收(Garbage Collection)是一种内存管理机制,用于检测和清理不再被程序使用的内存,这些不再被使用的内存就被称为垃圾。垃圾回收器会在 JS 引擎(浏览器或者 nodejs)内部周期性地运行,一般情况下无需开发者手动操作。

但是,了解垃圾回收机制的工作原理有助于我们写出更加高效的 JS 代码,使 JS 引擎更好的帮助我们完成垃圾回收,避免我们开发的应用出现内存泄漏问题。

垃圾是怎样产生的?

JS 中的数据类型有原始类型和引用类型,原始类型占用的内存极小,一般是字符串、数字、布尔值这些,他们被存放在栈(stack)中。引用类型可以是数组、普通对象或者函数,他们一般会包含较多的数据,所以引用类型的实际数据存放在内存的堆(heap)中,然后在栈中会存放一个指向该实际数据的地址。

const str = "abc" // 原始类型
const obj = { foo: "bar" } // 引用类型

在 JS 中每声明一个变量,该应用占用的内存就会相应的增加,但机器的内存是有限的,内存的占用不能无限制的增加。所以 JS 引擎需要适时的回收内存,释放内存,保留性能,从而运行使程序流畅运行。

垃圾回收机制会回收哪些垃圾?

当一个对象不在任何引用被引用时,它就变得不可达,垃圾回收器就需要将这些不可达对象标记为可回收,并在适当的时机回收它们的内存。

以下面这段代码为例:

function myFunction() {
  const obj = { foo: "bar" }
  // do something
}

myFunction()

这段代码中的 obj 对象在 myFunction 函数执行之后,就已经没有被引用了,就需要被回收。

但当某个对象从开发角度上来说不再被使用了,却意外的仍然在某个地方被引用,垃圾回收器就无法回收它的内存,就会造成内存泄漏(内存逐渐累积,程序占用的内存越来越多,当超过系统的可用内存时,就会造成程序崩溃)。

比如下面这段代码中 obj 对象就可能不会被回收:

function myFunction() {
  const obj = { foo: "bar" }

  setTimeout(() => {
    console.log(obj.foo)
  }, 1000)
}

myFunction()

因为 obj 作为闭包中的引用传递给了定时器的回调函数,即使 myFunction 执行完毕,由于定时器没有被清除,obj 仍然被定时器回调函数持有引用,就可能导致 obj 不会被垃圾回收。

垃圾回收的算法

JavaScript 中的垃圾回收机制主要基于以下两个原则:

引用计数(Reference Counting)

每个对象都有一个引用计数,用于记录有多少个引用指向该对象。当引用计数变为零时,表示没有任何引用指向该对象,因此该对象可以被回收。

标记-清除(Mark and Sweep)

这是一种更常见的垃圾回收算法。它从根对象(如全局对象、当前执行上下文中的变量等)开始,通过遍历对象之间的引用关系,标记所有可达的对象。然后,回收器会清除未标记的对象,即不可达的对象,释放其内存。

Chrome 和 nodejs 的垃圾回收算法

Chrome 和 nodejs 都采用了谷_歌开源的 V8 引擎。V8 引擎的垃圾回收机制采用了标记清除算法,但在此基础又做了一些优化。

V8 引擎将内存分为新生代(Young Generation)和老生代(Old Generation)。大多数对象在新生代中创建,经过一定时间后,如果它们仍然存活,就会被晋升到老生代。

Scavenger 垃圾回收(新生代)

新生代使用了 Scavenger 垃圾回收算法,它将内存划分为一个存活区域和一个空闲区域。对象首先被分配到存活区域,当存活区域满时,会执行垃圾回收操作,将存活的对象复制到空闲区域,并清空存活区域。

Mark-Sweep-Compact 垃圾回收(老生代)

老生代中使用了 Mark-Sweep-Compact(标记-清除-整理)垃圾回收算法。它首先标记所有的存活对象,然后清除掉未被标记的对象,最后进行内存整理,使存活对象连续排列,减少内存碎片。

增量垃圾回收

V8 引擎还支持增量垃圾回收。他会将垃圾回收操作分成多个小步骤执行,每个步骤之间会插入一些 JavaScript 代码的执行,从而避免长时间的垃圾回收造成的界面卡顿。

空闲时间垃圾回收

V8 引擎还在空闲时间执行部分垃圾回收操作,以充分利用闲置的计算资源。这些时间段可能是在程序等待用户输入、网络请求返回、或者其他暂时没有任务需要处理的情况下出现的。

需要手动清除的内存

垃圾回收机制会根据算法智能的回收大部分的内存,但由于业务逻辑的关系,它无法明确知道在我们的写的(垃圾)代码中,哪些对象其实是不再使用的,所以我们在开发过程中需要及时的清除不需要的事件监听、定时器、计时器,避免循环引用,以及避免使用闭包。

清除事件监听

const myButton = document.getElementById("myButton")

function handleClick() {
  console.log("Button clicked!")
}

// 添加事件监听器
myButton.addEventListener("click", handleClick)

// 在页面卸载或元素移除时解除事件监听器
window.addEventListener("beforeunload", () => {
  myButton.removeEventListener("click", handleClick)
})

执清除定时器、计时器

const timer = setTimeout(() => {}, 500)

// 在页面卸载或元素移除时解除事件监听器
window.addEventListener("beforeunload", () => {
  clearTimeout(timer)
})

手动调用垃圾回收

一般情况下我们无需手动调用垃圾回收,但有些浏览器支持主动触发垃圾回收。

IE 浏览器

if (typeof window.CollectGarbage === "function") {
  window.CollectGarbage()
}

Opera 浏览器

if (window.opera && typeof window.opera.collect === "function") {
  window.opera.collect()
}

本文转载于:

https://juejin.cn/post/7267434484505788468

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/888786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Baklib是比语雀、Notion、石墨文档更好用的在线知识库管理工具

在当今信息爆炸的时代,如何高效地管理和利用知识成为了每个人都面临的问题。在线知识库管理工具应运而生,帮助用户整理、存储和共享知识。在这篇文章中,我将介绍一个更好用的在线知识库管理工具——Baklib,并探讨它相对于其他知识…

Python爬虫——scrapy_多条管道下载

定义管道类(在pipelines.py里定义) import urllib.requestclass DangDangDownloadPipelines:def process_item(self, item, spider):url http: item.get(src)filename ../books_img/ item.get(name) .jpgurllib.request.urlretrieve(url, filename…

JAVA编程学习笔记

常用代码、特定函数、复杂概念、特定功能……在学习编程的过程中你会记录下哪些内容?快来分享你的笔记,一起切磋进步吧! 一、常用代码 在java编程中常用需要储备的就是工具类。包括封装的时间工具类。http工具类,加解密工具类&am…

上海亚商投顾:沪指震荡调整 房地产、券商板块逆势走强

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 市场情绪 三大股指今日继续调整,深成指尾盘跌近1%,科创50指数跌超1.7%。房地产板块逆势走强&#xf…

计算机视觉之三维重建(一)(摄像机几何)

针孔摄像机 添加屏障: 使用针孔(o光圈针孔摄像机中心),实现现实与成像一对一映射,减少模糊。其中针孔与像平面的距离为f(焦距);虚拟像平面位于针孔与真实物体之间,与像平面互为倒立关系。位置映射:利用相似…

最新SSD固态硬盘颗粒QLC、SLC、MLC、TLC详解

概要 本文从SSD结构出发,详细介绍NAND闪存芯片QLC、SLC、MLC、TLC之间的区别、各自的优缺点以及其适用的人群。目录一、剖析SSD二、什么是NAND闪存三、单层单元(Single Level Cell,简称SLC)四、多层单元(Multi Level C…

CAD图像转地形插件

插件介绍 CAD图像转地形插件可用于在AutoCAD软件内基于图片图像信息生成三维高度实体模型,适用于科研论文渲染绘图、有限元建模、地形模拟等方面的应用。 使用说明 对于一张图片来说,如灰度图,其图片信息是像素的亮度差异,这样一…

yolov5封装进ros系统

一,要具备ROS环境 ROS环境搭建可以参考我之前的文章 ROS参考文章1 ROS参考文章2   建立ROS工作空间 ROS系统由自己的编译空间规则。 cd 你自己想要的文件夹(我一般是home目录) mkdir -p (你自己的文件夹名字,比如我是yolov5…

团队中的意外:如何稳定船舶当风暴来临

项目管理不仅仅是任务分配和里程碑跟踪。在项目生命周期中,经常会遇到许多意想不到的挑战。其中之一就是团队成员的突然离职、生病或其他意外情况。作为项目经理,如何应对这些突发情况,确保项目的稳定进展,是检验项目经理能力的关…

(白帽黑客)自学笔记

一、前言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了. 2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发. 3.有时多 google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答. 4.遇到实在搞不懂的,可以先放放,以…

Linux下的thundersvm的安装经验

之前写过一篇文章是关于windows下安装thundersvm的。当初在linux下安装thundersvm很容易,因为我的CUDA正好是9.0版本。所以一句命令 pip install thundersvm 即可安装。 但如果CUDA版本不是9.0,安装就比较麻烦。本文记录的是一种可行的方法,但…

C语言刷题训练DAY.6

1.进制AB 解题思路&#xff1a; 这里我们按照备注的提示&#xff0c;调整输入格式。 注意&#xff1a;%x是十六进制的数字 %o是八进制的数字 解题代码&#xff1a; #include<stdio.h> int main() {int a 0;int b 0;scanf("0x%x 0%o", &a, &b);pri…

微信开发者工具项目简单介绍和使用

主要目录简介&#xff1a; 页面文件的简介&#xff1a; 四个json文件的简介&#xff1a; 1.app.json 2.project.config.json 3.sitemap.json 4.页面中的json 简单操作 1.快速新建小程序页面&#xff0c;在app.json的pages下编写页面的路径&#xff0c;保存后微信开发者工具会自…

数据结构与算法-Java篇

1.队列问题 队列是一个有序列表&#xff0c;可以用数组或是链表来实现。遵循先入先出的原则。即:先存入队列的数据&#xff0c;要先取出。后存入的要后取出 1.1 数组模拟队列 1.1.1 单列队列 MaxSize表示队列的容量因为队列的输出、输入是分别从前后端来处理&#xff0c;因此…

深度学习模型训练好后使用time.time()测试处理每一帧速度(时间)和模型推理速度(时间)

在深度学习中&#xff0c;如果想测试训练好的模型处理每一帧图像的运行时间&#xff0c;可以在模型预测代码段添加时间统计的逻辑: 目录 加载预训练模型遍历测试图像汇总统计预测测试集全部图像的平均处理时间测试结果样式 加载预训练模型 model torch.load(best_model.pth) …

图数据库的挑战是什么?

无论是什么数据库&#xff0c;如果不突出性能这个第一生产力&#xff0c;那么还有什么继续深入了解它的必要呢&#xff1f;图数据库尤其如此——因为图数据库解决的最主要的挑战就是传统数据库在面对深度数据间的关联关系时指数级性能下降、时耗增长的问题。 这里我们就不去赘述…

uni-app自定义多环境配置,动态修改appid

背景 在企业级项目开发中&#xff0c;一般都会分为开发、测试、预发布、生产等多个环境&#xff0c;在工程化中使用不同的打包命令改变环境变量解决不同环境各种变量需要手动修改的问题&#xff0c;比如接口请求地址&#xff0c;不同环境的请求路径前缀都是不同的。在使用uni-…

百度王海峰披露飞桨生态最新成果 开发者数量已达800万

8月16日&#xff0c;由深度学习技术及应用国家工程研究中心主办的WAVE SUMMIT深度学习开发者大会2023在北京举行。百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰做了主题演讲。王海峰首次对外表示&#xff0c;大语言模型具备了理解、生成、逻辑、记忆等人工智…

CAN协议

CAN总线特点&#xff1a; 多主机多从机 串行异步通讯、没时钟线 2.只有CAN_HIGH和CAN_LOW两条差分信号 3.连接方式多个节点挂在总线上&#xff0c;比较类似I2C总线&#xff0c;可以再SCL和SDA上挂载多个从 4.每个设备都是一个节点Node&#xff0c;节点直接可以相互通讯&#…

使用PHP实现随机调用图片

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 预览地址&#xff1a;ht…