”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > JavaScript 内存管理和垃圾收集

JavaScript 内存管理和垃圾收集

发布于2024-11-08
浏览:686

随着 JavaScript 应用程序的增长,优化性能变得至关重要。一个关键方面是有效管理内存。 JavaScript 的自动垃圾收集 (GC) 会有所帮助,但了解它的工作原理以及如何避免内存泄漏可以极大地提高应用程序的性能。这篇文章深入探讨了现代 JavaScript 引擎中的内存管理技术和高级 GC 行为。

JavaScript 中的内存分配
JavaScript 在声明变量时自动分配内存,并在不再需要时释放内存。然而,了解内存如何分配(堆栈与堆)对于在复杂应用程序中有效管理资源至关重要。

1。堆栈内存:

  • 存储原始值(例如数字、布尔值)。

  • LIFO(后进先出)访问,使得较小数据的速度更快。

2.堆内存:

  • 用于对象和函数等引用类型。

  • 更大、访问速度更慢,但灵活。

垃圾收集如何工作
JavaScript 使用标记和清除算法来删除未使用的内存。当一个对象不再被引用时,它就变成“垃圾”并且有资格被收集。然而,如果内存管理不善,对自动 GC 的依赖可能会导致问题。

  • Mark-and-Sweep: GC从根(全局执行上下文)开始标记可达对象,任何未标记的对象都被视为垃圾。

  • 分代垃圾收集: 许多 JavaScript 引擎(如 V8)使用分代 GC,其中内存被分为“年轻”和“老”代。年轻一代收集更频繁,而老一代处理长期存在的对象。

避免内存泄漏
即使使用自动 GC,如果无意中保留了对对象的引用,仍然可能会发生内存泄漏。常见原因包括:

  • 无意的全局变量: 不使用 let、const 或 var 可以创建全局变量,从而防止它们被垃圾收集。
function leak() {
  myGlobalVar = 'I am global';
}
  • 闭包:使用不当的闭包可能会保留对外部变量的引用超过所需的时间。
function outer() {
  let largeObject = { /* some data */ };
  return function inner() {
    console.log(largeObject);
  };
}
  • 事件侦听器: 忘记删除附加到 DOM 元素的事件侦听器可能会保留分配的内存,即使该元素从 DOM 中删除也是如此。
const element = document.getElementById('myButton');
element.addEventListener('click', () => console.log('Clicked'));
// Be sure to remove listeners when not needed
  • 分离的 DOM 节点: 如果 DOM 节点被删除但仍在代码中的其他地方引用,则不会释放内存。
const element = document.getElementById('myElement');
document.body.removeChild(element);

内存优化的高级技术

1.手动内存分析:使用浏览器开发人员工具来分析内存使用情况并检测泄漏或不必要的持久对象。

  • Chrome DevTools:堆快照的“内存”选项卡。

  • Firefox:内存泄漏的性能工具。

2.WeakMaps和WeakSets:当你想存储对象而不阻止垃圾回收时,使用WeakMap或WeakSet。当没有其他对象引用时,这些结构允许自动 GC。

let wm = new WeakMap();
let obj = {};
wm.set(obj, 'someValue');
obj = null; // 'obj' is now eligible for GC.

3.优化循环和递归:通过使用尾调用优化或迭代方法,避免递归函数中不必要的内存消耗。另外,请小心可能导致内存峰值的大循环或数组操作。

4.延迟和延迟加载:通过延迟或延迟加载不立即需要的脚本和资源来优化内存使用,防止不必要的内存消耗。

结论:

虽然 JavaScript 的垃圾收集器处理了大部分繁重的工作,但注意内存的分配和释放方式可以提高性能,特别是在复杂或长时间运行的应用程序中。通过应用这些内存管理策略,您将确保您的应用程序在扩展时保持高性能。


感谢您的阅读!请随意分享您的想法或您在自己的项目中使用的任何高级内存管理技巧。??
访问我的网站:https://shafayet.zya.me


给你一个模因?

JavaScript Memory Management and Garbage Collection

版本声明 本文转载于:https://dev.to/shafayeat/javascript-memory-management-and-garbage-collection-2a?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何使用 VLC 模块在 Python 中播放 MP3 歌曲?
    如何使用 VLC 模块在 Python 中播放 MP3 歌曲?
    使用 Python 播放 MP3 歌曲使用正确的工具,在 Python 中播放 MP3 歌曲可以非常简单。错误的做法:尝试使用wave模块打开MP3文件,如下图所示不推荐:import wave w = wave.open("e:/LOCAL/Betrayer/Metalik Klinik...
    编程 发布于2024-11-08
  • 如何为Apache PHP应用程序配置环境变量?
    如何为Apache PHP应用程序配置环境变量?
    Apache PHP 应用程序的环境变量配置开发依赖环境变量的 PHP 应用程序时,必须清楚地了解如何配置环境变量使用 Apache 时设置这些变量。本文旨在提供有关配置可在 PHP 中访问的环境变量的指导,确保 Web 应用程序的正确运行。具体来说,为同一服务器中的各个域配置单独的环境变量是一种常...
    编程 发布于2024-11-08
  • 如何从 Activity 访问 ViewPager 片段方法?
    如何从 Activity 访问 ViewPager 片段方法?
    从 Activity 访问 ViewPager Fragment 方法许多移动应用程序使用片段,即代表模块化屏幕部分的独立组件。使用视图分页器管理多个片段可实现流畅的导航和页面动画。有时,开发人员需要在片段中执行特定操作以响应外部事件,例如用户在视图寻呼机上滑动。然而,实现此功能可能会遇到某些挑战。...
    编程 发布于2024-11-08
  • 如何在 Python 中按列值对散点图着色?
    如何在 Python 中按列值对散点图着色?
    按列值对散点图着色在 Python 中,Matplotlib 库提供了多种自定义散点图美观的方法。一项常见任务是根据特定列中的值分配颜色。Seaborn 集成一种解决方案是利用基于 Matplotlib 构建的 Seaborn 库。 Seaborn 提供 sns.relplot 和 sns.Face...
    编程 发布于2024-11-08
  • 为什么 fmt.Printf 显示负整数的二进制表示与 Go 中预期的不同?
    为什么 fmt.Printf 显示负整数的二进制表示与 Go 中预期的不同?
    二进制补码和 fmt.Printf:解开二进制表示之谜处理有符号整数时,计算机使用二进制补码来表示负值。这与典型的二进制表示不同,其中符号由单独的位指示。例如,在二进制补码中,整数 -5 表示为 1111 1011。但是,使用 fmt.Printf 打印二进制表示形式可能会产生意外结果。例如,以下代...
    编程 发布于2024-11-08
  • 读取控制台输入
    读取控制台输入
    InputStream读取方法: read():允许您直接从流中读取字节。 read()的三个版本: int read():读取单个字节并在流末尾返回-1。 int read(byte data[]):读取字节,直到数据数组填满、到达流末尾或发生错误。返回读取的字节数,如果到达流末尾则返回 -1。 ...
    编程 发布于2024-11-08
  • PHP 构造函数属性推广初学者指南
    PHP 构造函数属性推广初学者指南
    PHP 8 引入了一个名为 构造函数属性提升 的奇妙功能。如果您是 PHP 或一般编程新手,这可能听起来有点复杂。但别担心!本博客将通过大量编码示例向您介绍它是什么、为什么有用以及如何使用它。开始吧! 什么是建筑商财产促销? 在 PHP 8 之前,创建具有属性的类并在构造函数中初始化...
    编程 发布于2024-11-08
  • 如何使用 CNTLM 访问工作场所代理后面的 pip?
    如何使用 CNTLM 访问工作场所代理后面的 pip?
    与 CNTLM 的 PIP 代理连接要使用 CNTLM 访问工作场所代理后面的 pip,用户可能会遇到 --proxy 选项的问题。然而,利用环境变量提供了可靠的解决方案。CNTLM 配置验证可以通过运行“cntlm.exe -c cntlm.ini -I -M http://google.com”...
    编程 发布于2024-11-08
  • 如何使用 MySQL 数据库中的时间序列数据填充 JFreechart TimeSeriesCollection?
    如何使用 MySQL 数据库中的时间序列数据填充 JFreechart TimeSeriesCollection?
    从 MySQL DB 填充 JFreechart TimeSeriesCollection此问题旨在使用 JFreechart TimeSeriesCollection 显示一个月中几天的温度变化。然而,最初的实现面临着从数据库中准确读取数据的挑战。时序数据的精确读取要解决数据读取问题,需要考虑之间...
    编程 发布于2024-11-08
  • ValueError:无法将 NumPy 数组转换为张量 - 已解决?
    ValueError:无法将 NumPy 数组转换为张量 - 已解决?
    ValueError: Failed to Convert NumPy Array to Tensor问题描述尝试使用 TensorFlow 训练具有 LSTM 层的神经网络时,出现以下情况发生错误:ValueError: Failed to convert a NumPy array to a T...
    编程 发布于2024-11-08
  • 为什么Java重载不能基于返回类型?
    为什么Java重载不能基于返回类型?
    Java 中的返回类型重载:不兼容尽管 Java 具有多方面的功能,但该语言在重载函数时还是存在限制仅通过更改返回类型。这就提出了一个常见的问题:为什么 Java 禁止这样的重载?答案在于重载的基本性质。重载允许多个具有相同名称的函数共存于一个类中,并通过它们的参数签名进行区分。然而,当返回类型也用...
    编程 发布于2024-11-08
  • 强密码生成器
    强密码生成器
    看看我做的这支笔!
    编程 发布于2024-11-08
  • Angular 和 15 的改进
    Angular 和 15 的改进
    1) 在没有构造函数的情况下在 Angular 14 中使用注入注入服务。 以前,注入任何服务总是需要具有构造函数的类: class MyClass { constructor(private myService: MyService) {} } 现在,我们可以在函数和类中注入服务。我们只需要声...
    编程 发布于2024-11-08
  • 面向对象编程:掌握 DSA 的第一步
    面向对象编程:掌握 DSA 的第一步
    Imagine you're walking through a bustling factory. You see different machines, each designed for a specific purpose, working together to create a fina...
    编程 发布于2024-11-08
  • 如何修复 Android 中的“java.lang.String 类型的值无法转换为 JSONObject”错误?
    如何修复 Android 中的“java.lang.String 类型的值无法转换为 JSONObject”错误?
    排除“java.lang.String 类型的值\u003cbr\u003e 无法转换为 JSONObject”错误在您的 Android 应用程序中,您遇到与 JSON 解析相关的错误。具体来说,您会看到以下异常:org.json.JSONException: Value <br of t...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3