记录--JS 的垃圾回收机制
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
垃圾回收(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
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--JS 的垃圾回收机制的更多相关文章
- js的垃圾回收机制
Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记 ...
- [转]js的垃圾回收机制
javascript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存.在编写javascript程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管 ...
- 记录Java的垃圾回收机制和几种引用
一.Java的垃圾回收机制 Java的垃圾回收机制(java garbage collection)是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的堆内存空间. ...
- JS基础-垃圾回收机制与内存泄漏的优化
[V8引擎]浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略 垃圾回收机制 如何判断回收内容 如何确定哪些内存需要回收,哪些内存不需要回收,这是垃圾回收期需要解决的最基本问题.我们可以这样 ...
- JavaScript--我发现,原来你是这样的JS(四)(看看变量,作用域,垃圾回收机制是啥)
一.介绍 这是红宝书(JavaScript高级程序设计 3版)的读书笔记第四篇,是红宝书第四章内容(主要是变量和作用域问题),当然其中还有我个人的理解.红宝书这本书可以说是难啃的,要看完不容易,挺厚的 ...
- JS--我发现,原来你是这样的JS(四)(看看变量,作用域,垃圾回收机制是啥)
一.介绍 这是红宝书(JavaScript高级程序设计 3版)的读书笔记第四篇,是红宝书第四章内容(主要是变量和作用域问题),当然其中还有我个人的理解.红宝书这本书可以说是难啃的,要看完不容易,挺厚的 ...
- 理解闭包的微观世界和JS垃圾回收机制
function a() { ; function b() { alert(++i); } return b; } var c = a(); c(); 一.闭包的微观世界 如果要更加深入的了解闭包以及 ...
- 浅尝js垃圾回收机制
局部作用域内的变量,在函数执行结束之后就会被js的垃圾回收机制销毁 为什么要销毁局部变量? => 为了释放内存 js垃圾回收机制何时会销毁局部变量 : 如果局部变量无法再得到访问,就会被 ...
- python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除
js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...
- js 垃圾回收机制和引起内存泄漏的操作
垃圾回收机制 JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记为“离开环境”.标记“离开环境”的就回收内存. 工作流程: ...
随机推荐
- 零基础入门Vue之拘元遣将——其他常用指令&自定义指令
回首 在 零基础入门Vue之梦开始的地方--插值语法 我记录了v-bind.v-on.v-model的学习 在 零基础入门Vue之To be or not to be--条件渲染 我记录了v-if.v ...
- JS Leetcode 220. 存在重复元素 III 题解分析,暴力解法与桶排序
壹 ❀ 引 今天的题目来自LeetCode 220. 存在重复元素 III,难度中等,题目描述如下: 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j, ...
- NC51179 选课
题目链接 题目 题目描述 学校实行学分制. 每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分. 学校开设了 N 门的选修课程,每个学生可选课程的数量 M 是给定的. 学生选修了这 M 门课 ...
- Linux IOS镜像中查看Kernel 版本号
开ISO镜像,到rpm包的目录里面去找到kernel-********.RPM这个包,中间的星号那一段就是内核版本
- Java设计模式-建造者模式Builder
介绍 建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式.它可以 将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方 法可以构造出不同表现(属性)的对象 ...
- Springboot中如何使用日志框架logback和log4j2?
说明 在这个简短的教程中,我们将探索 Spring Boot 中可用的主要日志记录选项:logback和log4j2 初始设置 使用 starters 时,默认使用 Logback 进行日志记录. 让 ...
- Ansible原理和安装
目录 Ansible Ansible简介 Ansible的特性 Ansible的基本组件 Ansible安装(rhel8/rhel9) 1. rhel8安装 1.1 配置epel源 1.2 安装ans ...
- dpt-shell 抽取壳实现原理分析(加壳逻辑)
开源项目位置(为大佬开源精神点赞) https://github.com/luoyesiqiu/dpt-shell 抽取壳分为两个步骤 加壳逻辑: 一 对apk进行解析,将codeItem抽出到一个文 ...
- 学习go语言编程之并发编程
并发基础 并发包含如下几种主流的实现模型: 多进程 多线程 基于回到的非阻塞/异步IO 协程 协程 与传统的系统级线程和进程相比,协程最大的优势在于"轻量级",可以轻松创建上百万个 ...
- MySQL重新设置auto_increment值
需求描述 通常,我们都会在数据库表中设置一个自增字段作为主键,该字段的值会随着添加新记录而自增. 同时也必须注意,这个自增字段的值只会一直增加,即使把记录删除了,该自增字段的值也不会变小. 因此,就会 ...
