垃圾回收之弱引用+实例说明+weakSet+weakMap

文章目录

    • 垃圾回收
      • 垃圾回收原理
      • 常见的垃圾回收方法
        • 1. 标记清除算法(Mark and Sweep)
        • 2. 标记整理算法(Mark and Compact)
        • 3. 复制算法(Copying)
        • 4. 分代回收算法(Generational Garbage Collection)
      • 手动触发垃圾回收
    • js中对象怎么做到弱引用
      • 1. `WeakMap`
        • 基本语法
        • 示例代码
        • 使用场景
      • 2. `WeakSet`
        • 基本语法
        • 示例代码
        • 使用场景
    • 垃圾回收与弱引用之间的关系
      • 弱引用与垃圾回收的关系
        • 强引用与垃圾回收
        • 弱引用与垃圾回收(WeakMap)
      • 应用场景
        • 1. 缓存数据
        • 2. 实现私有属性和方法
        • 3. 跟踪对象状态
      • 弱引用与垃圾回收(WeakSet )
      • 1. `WeakSet` 的基本概念
      • 2. `WeakSet` 与垃圾回收的关系
        • 强引用和弱引用对垃圾回收的影响
        • 垃圾回收时机
      • 3. `WeakSet` 的特性与垃圾回收的关联
      • 4. 示例代码
      • 5. 应用场景

垃圾回收

在 JavaScript 中,垃圾回收(Garbage Collection,简称 GC)是自动管理内存的机制,它负责回收不再被程序使用的内存空间,以避免内存泄漏,提高内存使用效率。下面详细介绍 JavaScript 垃圾回收的原理和常见方法。

垃圾回收原理

JavaScript 是一种使用自动内存管理的语言,其垃圾回收的核心原理基于可达性分析。即判断一个对象是否可以被程序访问到,如果一个对象无法通过任何可达的引用路径被访问,那么这个对象就被认为是“垃圾”,可以被回收。

常见的垃圾回收方法

1. 标记清除算法(Mark and Sweep)

这是最基础也是最常见的垃圾回收算法,现代浏览器大多采用这种算法的改进版本。其工作过程分为两个阶段:

  • 标记阶段:垃圾回收器从根对象(如全局对象 window)开始,遍历所有可达对象,并为它们标记。根对象是指那些在程序中可以直接访问的对象,例如全局变量、函数调用栈中的变量等。
  • 清除阶段:垃圾回收器遍历整个内存空间,将未被标记的对象视为垃圾,并释放它们所占用的内存空间。

示例解释

// 创建一个对象
let obj1 = { name: 'object1' };
let obj2 = { name: 'object2' };// obj1 引用 obj2
obj1.ref = obj2;// 移除对 obj2 的直接引用
obj2 = null;// 此时,obj2 仍然可以通过 obj1.ref 访问到,所以不会被标记为垃圾// 移除对 obj1 的引用
obj1 = null;// 现在 obj1 和 obj2 都无法从根对象访问到,在下一次垃圾回收时,它们将被标记并清除
2. 标记整理算法(Mark and Compact)

标记整理算法是标记清除算法的改进版本,它解决了标记清除算法可能导致的内存碎片化问题。其工作过程分为三个阶段:

  • 标记阶段:与标记清除算法相同,从根对象开始遍历,标记所有可达对象。
  • 整理阶段:将所有存活的对象向内存的一端移动,使它们连续存储,从而消除内存碎片。
  • 清除阶段:释放所有未被标记的对象所占用的内存空间。
3. 复制算法(Copying)

复制算法将内存空间分为两个相等的区域:一个是使用区(From Space),另一个是空闲区(To Space)。其工作过程如下:

  • 当程序运行时,所有对象都分配在使用区。
  • 当使用区内存不足时,垃圾回收器开始工作。它从根对象开始遍历,将所有存活的对象复制到空闲区。
  • 复制完成后,交换使用区和空闲区的角色,原来的使用区变为空闲区,原来的空闲区变为使用区。

优点:复制算法的效率较高,因为它只需要移动存活的对象,并且不会产生内存碎片。
缺点:需要额外的内存空间,因为要将内存分为两个区域,实际可用的内存只有一半。

4. 分代回收算法(Generational Garbage Collection)

分代回收算法基于一个经验观察:大多数对象的生命周期都很短,而少数对象的生命周期很长。因此,该算法将对象分为不同的代(Generation),不同代采用不同的垃圾回收策略。

  • 新生代(Young Generation):新创建的对象通常被分配到新生代。新生代使用复制算法进行垃圾回收,因为新生代中的对象大多很快就会死亡,复制算法可以高效地处理这些对象。
  • 老生代(Old Generation):经过多次垃圾回收仍然存活的对象会被晋升到老生代。老生代使用标记清除或标记整理算法进行垃圾回收,因为老生代中的对象生命周期较长,复制算法的效率较低。

手动触发垃圾回收

在 JavaScript 中,通常不建议手动触发垃圾回收,因为现代浏览器和 JavaScript 引擎会自动管理垃圾回收的时机,以优化性能。不过,在某些环境中(如 Node.js),可以使用以下方法手动触发垃圾回收:

if (global.gc) {global.gc();
}

需要注意的是,手动触发垃圾回收可能会影响程序的性能,应该谨慎使用。

js中对象怎么做到弱引用

在 JavaScript 里,ES6 引入了 WeakMapWeakSet 这两种数据结构来实现对象的弱引用。下面分别介绍它们的使用方式和特点。

1. WeakMap

WeakMap 是一种键值对集合,它的键必须是对象,并且这些对象是弱引用的。当对象的其他强引用都被移除后,WeakMap 中的键对象会被垃圾回收,对应的键值对也会自动从 WeakMap 中移除。

基本语法
const weakMap = new WeakMap();
示例代码
// 创建一个对象
const obj1 = {};
const obj2 = {};// 创建一个 WeakMap
const weakMap = new WeakMap();// 向 WeakMap 中添加键值对
weakMap.set(obj1, 'value for obj1');
weakMap.set(obj2, 'value for obj2');// 获取值
console.log(weakMap.get(obj1)); // 输出: 'value for obj1'// 检查某个键是否存在
console.log(weakMap.has(obj2)); // 输出: true// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // 输出: false// 当对象的其他强引用被移除后,WeakMap 中的键值对会自动被清理
let key = { name: 'temp' };
weakMap.set(key, 'temporary value');
key = null; // 移除对对象的强引用
// 一段时间后(垃圾回收执行时),该键值对会从 WeakMap 中消失
使用场景
  • 缓存数据:当你需要为对象关联一些额外的数据,并且不希望这些数据阻止对象被垃圾回收时,可以使用 WeakMap
  • 私有数据存储:可以使用 WeakMap 来模拟对象的私有属性。

2. WeakSet

WeakSet 是一种只存储对象的集合,这些对象也是弱引用的。与 WeakMap 类似,当对象的其他强引用被移除后,对象会从 WeakSet 中自动移除。

基本语法
const weakSet = new WeakSet();
示例代码
// 创建对象
const objA = {};
const objB = {};// 创建一个 WeakSet
const weakSet = new WeakSet();// 向 WeakSet 中添加对象
weakSet.add(objA);
weakSet.add(objB);// 检查对象是否存在于 WeakSet 中
console.log(weakSet.has(objA)); // 输出: true// 删除对象
weakSet.delete(objB);
console.log(weakSet.has(objB)); // 输出: false// 当对象的其他强引用被移除后,WeakSet 中的对象会自动被清理
let item = { id: 1 };
weakSet.add(item);
item = null; // 移除对对象的强引用
// 一段时间后(垃圾回收执行时),该对象会从 WeakSet 中消失
使用场景
  • 跟踪对象状态:可以使用 WeakSet 来跟踪某些对象是否处于某个特定状态,而不会影响对象的生命周期。

需要注意的是,WeakMapWeakSet 都没有迭代器,不能使用 for...of 循环,也没有 size 属性,因为它们的主要目的是提供弱引用功能,避免影响对象的垃圾回收。

垃圾回收与弱引用之间的关系

弱引用与垃圾回收的关系

在 JavaScript 中,垃圾回收(Garbage Collection,简称 GC)是自动管理内存的机制,其核心原则是回收不再被程序使用的内存空间,以避免内存泄漏。而弱引用是一种特殊的引用方式,它不会阻止对象被垃圾回收,二者存在紧密的联系:

强引用与垃圾回收

在正常情况下,当一个对象被其他变量或数据结构引用时,这种引用是强引用。只要存在强引用指向一个对象,该对象就不会被垃圾回收机制回收。例如:

const obj = { name: 'example' };
// 这里 obj 对对象 { name: 'example' } 是强引用
// 只要 obj 存在,这个对象就不会被垃圾回收
弱引用与垃圾回收(WeakMap)

JavaScript 中的 WeakMapWeakSet 实现了弱引用。当对象仅被 WeakMapWeakSet 引用时,这些引用不会阻止对象被垃圾回收。一旦对象的所有强引用都被移除,垃圾回收机制会在合适的时机回收该对象,同时 WeakMapWeakSet 中对应的引用也会自动消失。例如:

const weakMap = new WeakMap();
let key = { id: 1 };
weakMap.set(key, 'value');
// 此时 key 对对象 { id: 1 } 是强引用,weakMap 对它是弱引用key = null; 
// 移除了对对象 { id: 1 } 的强引用
// 当垃圾回收执行时,对象 { id: 1 } 会被回收,weakMap 中对应的键值对也会自动移除

应用场景

1. 缓存数据

在开发中,有时需要为某些对象缓存一些额外的数据,但又不希望缓存的数据阻止对象被垃圾回收。使用 WeakMap 可以很好地实现这一需求。

// 假设我们有一个函数需要为对象缓存一些计算结果
const cache = new WeakMap();function calculateAndCache(obj) {if (cache.has(obj)) {return cache.get(obj);}// 进行一些复杂的计算const result = /* 复杂计算逻辑 */ obj.id * 2;cache.set(obj, result);return result;
}let myObject = { id: 5 };
const result = calculateAndCache(myObject);
console.log(result);myObject = null; 
// 当 myObject 的强引用被移除后,它和对应的缓存数据都会被垃圾回收
2. 实现私有属性和方法

WeakMap 可以用来模拟对象的私有属性和方法,因为外部无法直接访问 WeakMap 中的数据,并且不会影响对象的生命周期。

const privateData = new WeakMap();class MyClass {constructor() {privateData.set(this, {secret: 'This is a private value'});}getSecret() {return privateData.get(this).secret;}
}const instance = new MyClass();
console.log(instance.getSecret()); instance = null; 
// 当 instance 的强引用被移除后,对象和对应的私有数据都会被垃圾回收
3. 跟踪对象状态

WeakSet 可以用于跟踪某些对象是否处于某个特定状态,而不会影响对象的生命周期。例如,在一个游戏中,跟踪哪些角色已经被标记为死亡。

const deadCharacters = new WeakSet();class Character {constructor(name) {this.name = name;}die() {deadCharacters.add(this);}isDead() {return deadCharacters.has(this);}
}const character1 = new Character('Hero');
character1.die();
console.log(character1.isDead()); character1 = null; 
// 当 character1 的强引用被移除后,它会从 deadCharacters 中自动移除

通过使用弱引用,可以更灵活地管理内存,避免因不必要的引用导致的内存泄漏问题。

弱引用与垃圾回收(WeakSet )

1. WeakSet 的基本概念

WeakSet 是 JavaScript 中的一种数据结构,它是一个集合,只能存储对象,并且这些对象是弱引用的。这意味着 WeakSet 中的对象不会阻止垃圾回收机制对它们的回收。

2. WeakSet 与垃圾回收的关系

强引用和弱引用对垃圾回收的影响
  • 强引用:当一个对象被其他变量或数据结构以常规方式引用时,这种引用是强引用。只要存在强引用指向一个对象,该对象就不会被垃圾回收。例如:
const obj = { key: 'value' };
// 这里 obj 对 { key: 'value' } 是强引用,只要 obj 存在,这个对象就不会被回收
  • 弱引用WeakSet 中的对象是弱引用。如果一个对象仅被 WeakSet 引用,而没有其他强引用指向它,那么该对象就可以被垃圾回收。当对象被垃圾回收后,它会自动从 WeakSet 中移除。例如:
const weakSet = new WeakSet();
let obj = { key: 'value' };
weakSet.add(obj);
// 此时 obj 对 { key: 'value' } 是强引用,weakSet 对它是弱引用obj = null; 
// 移除了对对象 { key: 'value' } 的强引用
// 当垃圾回收执行时,对象 { key: 'value' } 会被回收,并且会自动从 weakSet 中移除
垃圾回收时机

JavaScript 的垃圾回收机制是自动且不可预测的,它会在内存达到一定阈值或者空闲时触发。因此,我们无法精确知道对象何时会从 WeakSet 中被移除,但可以确定的是,一旦对象的所有强引用被移除,它最终会被回收,并且会从 WeakSet 中消失。

3. WeakSet 的特性与垃圾回收的关联

  • 不能遍历WeakSet 没有 forEach 方法,也不能使用 for...of 循环,因为其成员随时可能被垃圾回收,遍历可能会导致结果不一致。
  • 没有 size 属性:由于 WeakSet 中的对象可能随时被回收,size 属性的值会不断变化,因此 WeakSet 没有 size 属性。

4. 示例代码

// 创建一个 WeakSet
const weakSet = new WeakSet();// 创建对象
const obj1 = { id: 1 };
const obj2 = { id: 2 };// 将对象添加到 WeakSet 中
weakSet.add(obj1);
weakSet.add(obj2);// 检查对象是否存在于 WeakSet 中
console.log(weakSet.has(obj1)); // 输出: true// 移除对 obj1 的强引用
obj1 = null;// 此时垃圾回收机制可能还未执行,obj1 可能还在 WeakSet 中
// 当垃圾回收执行后,obj1 会被回收,并且会自动从 WeakSet 中移除// 手动触发垃圾回收(在某些环境中可能有效)
if (global.gc) {global.gc();
}// 再次检查 obj1 是否存在于 WeakSet 中
console.log(weakSet.has(obj1)); // 输出: false(假设垃圾回收已执行)

5. 应用场景

  • 跟踪对象状态:可以使用 WeakSet 来跟踪某些对象是否处于某个特定状态,而不会影响对象的生命周期。例如,在一个图形库中,跟踪哪些图形元素已经被标记为隐藏。
const hiddenElements = new WeakSet();class GraphicElement {constructor(id) {this.id = id;}hide() {hiddenElements.add(this);}isHidden() {return hiddenElements.has(this);}
}const element = new GraphicElement(1);
element.hide();
console.log(element.isHidden()); element = null; 
// 当 element 的强引用被移除后,它会从 hiddenElements 中自动移除

通过使用 WeakSet,可以避免因不必要的引用导致的内存泄漏问题,让对象在不再被使用时能够及时被垃圾回收。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wax到底是什么意思

在很久很久以前,人类还没有诞生文字之前,人类就产生了语言;在诞生文字之前,人类就已经使用了语言很久很久。 没有文字之前,人们的语言其实是相对比较简单的,因为人类的生产和生活水平非常低下,…

从理论到实践:Linux 进程替换与 exec 系列函数

个人主页:chian-ocean 文章专栏-Linux 前言: 在Linux中,进程替换(Process Substitution)是一个非常强大的特性,它允许将一个进程的输出直接当作一个文件来处理。这种技术通常用于Shell脚本和命令行操作中…

Python 中最大堆和最小堆的构建与应用:以寻找第 k 大元素为例

引言 在数据处理和算法设计中,堆(Heap)是一种非常重要的数据结构。它是一种特殊的完全二叉树,具有高效的插入和删除操作特性,时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)。堆主要分为最大堆和最小堆,…

使用Avalonia UI实现DataGrid

1.Avalonia中的DataGrid的使用 DataGrid 是客户端 UI 中一个非常重要的控件。在 Avalonia 中,DataGrid 是一个独立的包 Avalonia.Controls.DataGrid,因此需要单独通过 NuGet 安装。接下来,将介绍如何安装和使用 DataGrid 控件。 2.安装 Dat…

21款炫酷烟花代码

系列专栏 《Python趣味编程》《C/C趣味编程》《HTML趣味编程》《Java趣味编程》 写在前面 Python、C/C、HTML、Java等4种语言实现21款炫酷烟花的代码。 Python Python烟花① 完整代码:Python动漫烟花(完整代码) ​ Python烟花② 完整…

为什么LabVIEW适合软硬件结合的项目?

LabVIEW是一种基于图形化编程的开发平台,广泛应用于软硬件结合的项目中。其强大的硬件接口支持、实时数据采集能力、并行处理能力和直观的用户界面,使得它成为工业控制、仪器仪表、自动化测试等领域中软硬件系统集成的理想选择。LabVIEW的设计哲学强调模…

Cmake学习笔记

cmake的使用场景和功能:cmake 的诞生主要是为了解决直接使用 makeMakefile 这种方式无法实现跨平台的问题,所以 cmake 是可以实现跨平台的编译工具这是它最大的特点。cmake 仅仅只是根据不同平台生成对应的 Makefile,最终还是通过 make工具来…

计算机网络 应用层 笔记1(C/S模型,P2P模型,FTP协议)

应用层概述: 功能: 常见协议 应用层与其他层的关系 网络应用模型 C/S模型: 优点 缺点 P2P模型: 优点 缺点 DNS系统: 基本功能 系统架构 域名空间: DNS 服务器 根服务器: 顶级域…

基于WiFi的智能照明控制系统的设计与实现(论文+源码)

1系统方案设计 本设计智能照明控制系统,结合STM32F103单片机、光照检测模块、显示模块、按键模块、太阳能板、LED灯模块、WIFI模块等器件构成整个系统,在功能上可以实现光照强度检测,并且在自动模式下可以自动调节照明亮度,在手动…

openRv1126 AI算法部署实战之——TensorFlow TFLite Pytorch ONNX等模型转换实战

Conda简介 查看当前系统的环境列表 conda env list base为基础环境 py3.6-rknn-1.7.3为模型转换环境,rknn-toolkit版本V1.7.3,python版本3.6 py3.6-tensorflow-2.5.0为tensorflow模型训练环境,tensorflow版本2.5.0,python版本…

【react+redux】 react使用redux相关内容

首先说一下,文章中所提及的内容都是我自己的个人理解,是我理逻辑的时候,自我说服的方式,如果有问题有补充欢迎在评论区指出。 一、场景描述 为什么在react里面要使用redux,我的理解是因为想要使组件之间的通信更便捷…

JAVA安全—反射机制攻击链类对象成员变量方法构造方法

前言 还是JAVA安全,哎,真的讲不完,太多啦。 今天主要是讲一下JAVA中的反射机制,因为反序列化的利用基本都是要用到这个反射机制,还有一些攻击链条的构造,也会用到,所以就讲一下。 什么是反射…

vim交换文件的作用

1.数据恢复:因为vim异常的退出,使用交换文件可以恢复之前的修改内容。 2.防止多人同时编辑:vim检测到交换文件的存在,会给出提示,以避免一个文件同时被多人编辑。 (vim交换文件的工作原理:vim交换文件的工作…

无用知识之:std::initializer_list的秘密

先说结论,用std::initializer_list初始化vector,内部逻辑是先生成了一个临时数组,进行了拷贝构造,然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化,这个动作又触发了拷贝…

CoRAG 来自微软与人大的创新RAG框架技术

微软与人大合作开发的CoRAG(Chain-of-Retrieval Augmented Generation)是一种创新的检索增强生成(RAG)框架,旨在通过模拟人类思考方式来提升大语言模型(LLM)在复杂问题上的推理和回答能力。以下是对CoRAG的深度介绍: 1. CoRAG的核心理念 CoRAG的核心思想是通过动态调…

一文讲解HashMap线程安全相关问题(上)

HashMap不是线程安全的,主要有以下几个问题: ①、多线程下扩容会死循环。JDK1.7 中的 HashMap 使用的是头插法插入元素,在多线程的环境下,扩容的时候就有可能导致出现环形链表,造成死循环。 JDK 8 时已经修复了这个问…

网络基础知识

1 互联网本质 ​ 互联网(英语:Internet)是指20世纪末期兴起电脑网络与电脑网络之间所串连成的庞大网络系统。这些网络以一些标准的网络协议相连。它是由从地方到全球范围内几百万个私人、学术界、企业和政府的网络所构成,通過电子…

DeepSeek R1本地化部署 Ollama + Chatbox 打造最强 AI 工具

🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 Ollama 🦋 下载 Ollama🦋 选择模型🦋 运行模型🦋 使用 && 测试 二:🔥 Chat…

012-51单片机CLD1602显示万年历+闹钟+农历+整点报时

1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台,可以根据需要自行焊接模块,这是用立创EDA画的一个双层PCB板,所以模块都是插针式,不是表贴的。电路原理图在文末的链接里,PCB图暂时不选择开源。 B站上传的…

首发!ZStack 智塔支持 DeepSeek V3/R1/ Janus Pro,多种国产 CPU/GPU 可私有化部署

2025年2月2日,针对日益强劲的AI推理需求和企业级AI应用私有化部署场景(Private AI),云轴科技 ZStack 宣布 AI Infra 平台 ZStack 智塔全面支持企业私有化部署 DeepSeek V3/R1/ Janus Pro三种模型,并可基于海光、昇腾、…