JavaScript 内存泄漏

文章介绍了JavaScript中的内存使用和垃圾回收机制,强调了程序对内存失去控制权导致的内存泄漏问题。常见的内存泄漏场景包括意外的全局变量、console.log的使用以及不当的闭包引用。防止内存泄漏的方法包括清除不必要的引用、避免过多全局变量和及时清理DOM对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存的释放流程:

  1. 分配内存
  2. 内存中的读写
  3. 垃圾回收

对于内存的使用,所有语言基本都是一样的,只是更底层的语言在对于 ”分配内存“ 和 ”使用内存“ 是明确的,但是在高级语言中(比如本文的 JS)是隐藏了。
JS 中在定义一个变量时,就已经分配好了一个内存;
同时,内部也提供好了垃圾回收的机制,回收那些已经不再使用的内存。

原理:

  • 当我们定义了一个变量后,这个变量就会被垃圾回收机制所标记;
  • 当一次程序执行以后,如果这个变量依然存在引用,则垃圾回收机制会认为:变量还在使用,不能释放
  • 内存泄漏的原因:程序任务一个变量已经没用了,可是垃圾回收机制认为他还在使用,从而导致这段内存无法释放。
    • 这里需要注意的是:是程序对这段内存失去了控制权。
    • 内存突然暴增,并不是内存泄漏。

请添加图片描述

上图中,我录制了一个最基础的内存使用:在百度中(input)输入文字,触发高频 change 事件:
在这里插入图片描述

于是我们得到了上图中的这条监听内存的曲线:

  • 这条蓝色的线条中,我用黄色色圈出来的部分是手动清理了内存后,内存骤降的两个时机
  • 黄色圈出来的部分是指程序中,在我操作前后内存的变化,可以看到这里录制前后(停止输入后)内存的使用并没有多出来内存,说明这里的 GC 后内存的控制在程序可掌控的范围内。

以上就是一个简单的内存完整释放的例子。

那么有哪些场景容易造成内存泄露呢?

一、全局变量

请添加图片描述

分析上图,我们在给 window 变量设置了十万个属性,在这个全局变量下的内存是不会被垃圾回收的,这里多出来的那一步分内存就是程序失去对这些变量控制权的部分:
在这里插入图片描述
所以意外的全局变量泄露

二、console.log()

请添加图片描述
上图执行一段打印逻辑;

将上述结果放大后,可以清晰的看到,两次清理 GC 后,内存得到了一定的释放,但是有超出的那一部分内存造成了内存泄漏:
在这里插入图片描述
console.log 也是全局变量

这也是为什么,生产环境中都会要求删除 console 的原因了
当然,让客户看到 console 丢人也是一个原因

三、闭包

闭包本身并不会造成内存泄漏,没有控制好闭包的使用,导致变量的引用无法被回收才是闭包导致内存泄漏的原因。

请添加图片描述

直接看两次清除 GC 后的情况:在这里插入图片描述
可以看到第二次清除 GC 后,依然有一部分内存没有得到释放,这部分就是闭包引用导致的内存泄漏。
而常规的闭包引用的函数执行并不会造成内存泄漏。

四、Dom 泄漏

现代的前端框架几乎都不推荐直接操作 dom 了,因为 dom 也是对象,创建的 dom 对象在被使用后,没有及时清理掉也会造成一定程度的内存泄漏。

总结

所谓内存泄漏就是程序执行完了,本该随着程序执行结束而被释放的内存由于有着引用关系而未得到释放导致的内存占用问题。

小结一下防止内存泄漏的几个方面:

  1. 清除不必要的引用
  2. 尽量不要定义全局变量(比如减少 var 操作符的使用)
  3. 提交代码前删除 console
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值