细读 JS | 浅谈内存泄露、内存溢出

简介: 细读 JS | 浅谈内存泄露、内存溢出

前言


讲真,这两个概念很容易被混为一谈。


正文


一、内存


在 JavaScript 中,没有像 C 语言等提供有内存管理接口,JavaScript 是在创建变量时自动进行分配内存,并且在不使用它们时“自动”释放。释放的过程被称为“垃圾回收”。


这个“自动”就是混乱的根源,并让 JavaScript 开发者错误地认为他们可以不用关心内存管理。


内存的生命周期


不管什么程序语言,内存的生命周期基本是一致的:

  1. 分配你所需要的内存
  2. 使用分配到的内存(读、写)
  3. 不需要时,将其释放/归还

所有语言第二部分都是明确的。第一和第三部分在底层语言中是明确的,但在像 JavaScript 这些高级语言中,大部分都是隐含的。


内存管理的难题


大多数内存管理的问题都在“当内存不需要使用时释放”这个阶段。最困难的就是如何界定并找到“哪些被分配的内存确实不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。

高级语言解释器嵌入了“垃圾回收器”,它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。这只能是一个近似的过程,因为要知道是否仍然需要某块内存是无法判定的(无法通过某种算法解决)


垃圾回收(Garbage Collection,GC)


由于一些内存“不再需要”的问题无法判定,因此,垃圾回收实现只能有限制的解决一般问题。

  • 引用计数算法
    最初的垃圾回收算法,它把“对象是否不再需要”简化为“对象有没有其他对象引用到它”。如果没有引用指向改对象(零引用),对象将被垃圾回收机制回收。但是这个算法有个限制,无法处理循环引用的情况。
    关于“引用”的概念,一个对象如果有访问另一个对象的权限(显式或隐式),叫做一个对象引用另一个对象。
  • 标记清除算法
    这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。
    这个算法假定设置一个叫做根对象(在 Javascript 里是 globalThis 对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。
    它解决了早期算法无法处理循环引用的问题,但还是有一个限制:那些无法从根对象查询到的对象都将被清除(实际中很少会碰到这种情况)。
    从 2012 年起,所有现代浏览器都使用了标记清除垃圾回收算法。所有对 JavaScript 垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。


所以,通常我们不会在全局作用域下进行过多的变量或函数声明,更推荐将它们放在立即执行函数表达式(IIFE)内进行声明。否则它们将无法被垃圾回收,即在程序的生命周期内一直存在。


这一小节提到的“对象”,不仅特指 JavaScript 对象,还包括函数作用域、全局作用域。


二、内存泄露、溢出


区别


这两个概念是存在区别的。

  • 内存溢出(Out of Memory)
    当系统无法提供应用程序所需内存时,会导致应用程序抛出内存溢出的错误。
  • 内存泄露(Memory Leak)
    应用程序中一些被分配的内存,在使用完之后,没有及时被垃圾回收器进行回收(释放),导致一部分无效的内存被占用着。

当内存泄露积累到一定程度,就会发生内存溢出。而内存溢出导致的结果是应用程序被杀死。

场景


  1. 内存溢出

const obj = {}
for (let i = 0; i < 10000; i++) {
  obj[i] = new Array(1000000)
}
// 将会崩溃


  1. 内存泄露
  • 意外的全局变量
  • 闭包
  • setInterval 没有及时清除
  • DOM 引用未移除
  • ...


未完待续...

目录
相关文章
|
16天前
|
Web App开发 监控 JavaScript
监控和分析 JavaScript 内存使用情况
【10月更文挑战第30天】通过使用上述的浏览器开发者工具、性能分析工具和内存泄漏检测工具,可以有效地监控和分析JavaScript内存使用情况,及时发现和解决内存泄漏、过度内存消耗等问题,从而提高JavaScript应用程序的性能和稳定性。在实际开发中,可以根据具体的需求和场景选择合适的工具和方法来进行内存监控和分析。
|
16天前
|
JavaScript 前端开发 Java
避免 JavaScript 中的内存泄漏
【10月更文挑战第30天】避免JavaScript中的内存泄漏问题需要开发者对变量引用、事件监听器管理、DOM元素操作以及异步操作等方面有深入的理解和注意。通过遵循良好的编程实践和及时清理不再使用的资源,可以有效地减少内存泄漏的风险,提高JavaScript应用程序的性能和稳定性。
|
29天前
|
存储 JavaScript 前端开发
JS 中的内存管理
【10月更文挑战第17天】了解和掌握 JavaScript 中的内存管理是非常重要的。通过合理的内存分配、及时的垃圾回收以及避免内存泄漏等措施,可以确保代码的高效运行和稳定性。同时,不断关注内存管理的最新发展动态,以便更好地应对各种挑战。在实际开发中要时刻关注内存使用情况,以提升应用的性能和质量。
27 1
|
21天前
|
监控 JavaScript 前端开发
如何检测和解决 JavaScript 中内存泄漏问题
【10月更文挑战第25天】解决内存泄漏问题需要对代码有深入的理解和细致的排查。同时,不断优化和改进代码的结构和逻辑也是预防内存泄漏的重要措施。
35 6
|
21天前
|
JavaScript 前端开发 Java
JavaScript 中内存泄漏的几种常见情况
【10月更文挑战第25天】实际上还有许多其他的情况可能导致内存泄漏。为了避免内存泄漏,我们需要在开发过程中注意及时清理不再需要的资源,合理使用内存,并且定期检查内存使用情况,以确保程序的性能和稳定性
29 2
|
24天前
|
存储 JavaScript 前端开发
js 中有哪几种内存泄露的情况
JavaScript 中常见的内存泄漏情况包括:1) 全局变量未被释放;2) 意外的全局变量引用;3) 被遗忘的计时器或回调函数;4) 事件监听器未被移除;5) 子元素存在时删除父元素;6) 循环引用。
|
1月前
|
缓存 监控 JavaScript
|
1月前
|
存储 缓存 JavaScript
|
1月前
|
JavaScript 前端开发 算法
深入理解JavaScript的内存管理机制
【10月更文挑战第13天】深入理解JavaScript的内存管理机制
32 0
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
97 2
下一篇
无影云桌面