浅谈内存泄漏

内存泄漏

概念

在JavaScript中,内存泄漏是指应用程序在不再需要使用某块内存时仍然保持对其的引用,导致内存不能被垃圾回收机制释放,最终导致内存占用过高,性能下降。

内存泄漏通常发生在以下情况:

  • 全局变量:全局变量会一直存在于内存中,即使在不需要时也无法被垃圾回收机制回收。
    未清理的定时器和回调函数:如果定时器或回调函数没有正确清理,它们将一直存在于内存中,即使它们已经完成或不再需要了。
  • DOM引用:当从DOM中删除元素时,如果仍然保持对该元素的引用,它将会在内存中留下无法释放的引用。
  • 闭包:如果函数创建了一个闭包(即函数内部引用了外部函数的变量),并且闭包没有在正确的时机释放,这将导致外部函数的变量一直无法被垃圾回收。

为了避免内存泄漏,可以采取以下措施:

  • 使用局部变量:在函数内部尽量使用局部变量而不是全局变量,以便在函数执行完毕后可以被垃圾回收。
  • 显式清理:在不再需要使用的定时器、回调函数和DOM引用时,手动清理它们,例如通过使用clearTimeout()清除定时器。
  • 解除闭包:在不需要使用闭包时,手动解除对外部函数变量的引用,以便垃圾回收机制可以释放内存。
  • 使用垃圾回收器:JavaScript具有自动的垃圾回收机制,可以自动释放不再需要的内存。通过确保代码的正确性和效率,可以帮助垃圾回收器更好地工作。

常见的内存泄漏

全局变量

  1. 意外的全局变量

    function leakFunction() {leakVar = 'test'
    }
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    解决方法use strict 启用严格模式,严格模式会阻止创建意外的全局变量

  2. 全局变量未释放

    全局变量未释放也会导致内存泄漏,可通过将变量置为null释放全局变量,避免内存泄漏

    // 未释放的全局变量
    var globalVar = 'Hello'function doSomething() {
    // ...
    }// 忘记释放全局变量// 可通过以下方式释放
    // globalVar = null
    // doSomething = null
    

闭包

闭包 中被访问的参数和变量不会被JavaScript的垃圾回收机制回收,会导致内存泄漏,可通过将变量置为null释放全局变量,避免内存泄漏

function createClosure() {var value = 'Hello'// 创建一个闭包函数function closureFunction() {console.log(value)}// 返回闭包函数return closureFunction
}// 创建闭包
var closure = createClosure()// 闭包持有外部变量的引用,可能导致内存泄漏// 可通过以下方式释放
// closure = null

定时器未清理

未清理定时器也会导致内存泄漏,可通过clearInterval清理定时器,避免内存泄漏

// 创建一个定时器
var timer = setInterval(function() {// 定时器回调函数// ...
}, 1000)// 定时器未清理// 可通过以下方式清理定时器
// clearInterval(timer)

清除页面dom元素不完全

  1. 清除页面dom元素时,dom元素绑定的事件未解绑
var element = document.getElementById('button')
var counter = 0
function onClick(event) {counter++element.innerHtml = 'clickTime ' + counter
}element.addEventListener('click', onClick)// 可通过以下方式清理
// element.removeEventListener('click', onClick)
// element.parentNode.removeChild(element)

循环引用

当两个或多个对象之间存在相互引用,并且没有被其他对象引用,就会发生循环引用,从而导致内存泄漏。这种情况可以通过在对象之间断开引用来避免

function createObject() {var obj1 = {}var obj2 = {}obj1.ref = obj2obj2.ref = obj1return obj1
}
var myObj = createObject()
// 这里无法回收 myObj 和 myObj.ref 所占用的内存空间,导致内存泄漏

常见的防止内存泄露方法

  1. 显式释放引用

    在不再使用变量、对象或函数时,手动将其引用置为null,以便垃圾回收器可以正确地回收内存

    var obj = {}// 使用obj// 当不再需要obj时,将其引用置为null
    obj = null
    
  2. 清除定时器

    在使用setInterval或setTimeout函数创建定时器时,应确保在不需要时及时清除定时器。可以使用clearInterval或clearTimeout函数来清除定时器

    var timer = setInterval(function() {
    // 定时器回调函数
    // ...// 当不再需要定时器时,清除定时器
    clearInterval(timer)
    }, 1000)
    
  3. 移除事件监听器

    在使用addEventListener函数添加事件监听器时,确保在不需要时移除事件监听器,以避免对象无法被垃圾回收。可以使用removeEventListener函数来移除事件监听器

    var button = document.createElement('button')function handleClick() {
    // 点击事件回调函数
    // ...// 当不再需要事件监听器时,移除事件监听器
    button.removeEventListener('click', handleClick)
    }// 添加点击事件监听器
    button.addEventListener('click', handleClick)
    
  4. 避免创建不必要的闭包

    闭包可以使函数保持对其定义时的作用域的引用,从而可能导致内存泄漏。尽量避免在不需要时创建不必要的闭包

    function createClosure() {var value = 'Hello'// 创建一个闭包函数function closureFunction() {console.log(value)}// 返回闭包函数return closureFunction
    }// 创建闭包
    var closure = createClosure()// 当不再需要闭包时,释放闭包引用
    closure = null
    

相关文档

【温故而知新】JavaScript中内存泄露有那几种

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

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

相关文章

【补充】图神经网络前传——Node2vec

Node2Vec【图神经网络论文精读】_哔哩哔哩_bilibili 解决的问题:图嵌入 把每一个节点编码成一个d维的低维、稠密(不是one-hot)、连续(不是离散的,是实数->有助于保存更多的信息)向量,并且&a…

OpenHarmony标准设备应用开发(二)——布局、动画与音乐

本章是 OpenHarmony 标准设备应用开发的第二篇文章。我们通过知识体系新开发的几个基于 OpenHarmony3.1 Beta 标准系统的样例:分布式音乐播放、传炸弹、购物车等样例,分别介绍下音乐播放、显示动画、动画转场(页面间转场)三个进阶…

我与C++的爱恋:string类的常见接口函数

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:我与C的爱恋 朋友们大家好啊,本节我们来到STL内容的第一部分:string类接口函数的介绍 ​ ​ 1.string类的认识 给大家分享一个c文档 https://legacy.cplusplus.…

【C语言每日题解】用函数来模拟实现strlen()、strcpy()、strcmp()、strcat()

🥰欢迎关注 轻松拿捏C语言系列,来和 小哇 一起进步!✊ 学习了函数后,老师让我们用函数来实现上面这四个字符串函数。 我们首先来了解一下这四个字符串函数: 1.strlen函数 用于获取字符串长度(不包括末尾…

【Linux 网络】网络基础(二)(应用层协议:HTTP、HTTPS)-- 详解

我们程序员写的一个个解决我们实际问题,满足我们日常需求的网络程序,都是在应用层。 前面写的套接字接口都是传输层经过对 UDP 和 TCP 数据发送能力的包装,以文件的形式呈现给我们,让我们可以进行应用层编程。换而言之&#xff0c…

测试之路 - 精准而优雅

引子 这几年业内一直在做精准测试,大都使用工具 diff 代码改动、分析代码覆盖率这些平台集成的能力。 业务测试中,我们在技术设计和代码实现的基础上也做了一些精减和精准的测试实践,通过深入测试有针对的设计 case,发现隐藏问题…

RALL-E: Robust Codec Language Modeling with Chain-of-Thought Prompting for TTS

demo pageDetai Xin, tanxu微软 & 东大 & 浙大 abstract 使用CoT的思路,和Valle的框架,先实现LLM预测音素级别pitch/duration,然后预测speech token。 methods Prosody tokens as chain-of-thought prompts 和Valle一…

uac驱动之const修饰的变量和const修饰的指针

const int*p // p所指向的空间是常量 不可修改 ,但p可以修改 int*const p // p所指向的空间是可以修改 ,p不可以修改 #include <stdio.h> #include <string.h>struct usb_string {char id;const char *s; };enum {STR_ASSOC,STR_AC_IF,STR_USB_OUT_IT,STR_USB_O…

20232803 2023-2024-2 《网络攻防实践》实践九报告

目录 1.实践内容2.实践过程2.1 手工修改可执行文件&#xff0c;改变程序执行流程&#xff0c;直接跳转到getShell函数2.2 利用foo函数的Bof漏洞&#xff0c;构造一个攻击输入字符串&#xff0c;覆盖返回地址&#xff0c;触发getShell函数2.3 注入一个自己制作的shellcode并运行…

优秀博士学位论文分享:复杂场景下高精度有向目标检测的研究

优秀博士学位论文代表了各学科领域博士研究生研究成果的最高水平&#xff0c;本公众号近期将推出“优秀博士学位论文分享”系列文章&#xff0c;对人工智能领域2023年优秀博士学位论文进行介绍和分享&#xff0c;方便广大读者了解人工智能领域最前沿的研究进展。 “博士学位论…

VMware17虚拟机安装Kali Linux2024详解

目录 简介 一、环境搭建 二、下载ISO镜像 三、新建虚拟机 为虚拟机选择合适的操作系统类型和版本 分配适当的内存、硬盘空间和其他虚拟机配置选项 四、硬件配置 编辑虚拟机设置 选择安装介质 五、界面化安装配置 简介 Kali Linux是一个基于Debian的Linux发行版&#…

PopupMenuButton 颜色设置

前言&#xff1a; 今天在使用 flutter PopupMenuItem 的时候想设置它的选中颜色 和 点击颜色的时候&#xff0c;发现并没有相应的属性设置&#xff0c;后才测试才发现是需要 通过 Theme属性 来设置的 正确姿势&#xff1a; 是要通过 Theme 属性来设置&#xff0c;我这只是临时…