前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内存泄露与垃圾回收机制

内存泄露与垃圾回收机制

原创
作者头像
剁椒鱼鳞
发布2023-05-29 09:29:40
2490
发布2023-05-29 09:29:40
举报
文章被收录于专栏:前端小学生前端小学生

一、内存泄露

不再使用的内存,没有及时被释放,机会造成内存泄露

二、垃圾回收机制

因为收回过程内存开销比较大,且堵塞其他操作,所以V8引擎会周期性的释放那些不再使用的变量,进而释放内存

1. 全局变量:生命周期较长,直到卸载当前页面才会回收

2. 局部变量:如函数内的变量(排除个别闭包),一旦函数执行完毕,该变量即会被回收

2. 闭包:分为两种,一种是程序自动生成的闭包,会遵循局部变量规则,但手动生成的闭包,V8引擎不会自动回收,需要开发者人为的将变量置为null,才会被回收。后期单独讲解闭包

三、方式

主要分为两种,标记清除和引用计数

1. 标记清除:

变量进入执行上下文时,会打个进入环境的标记,当离开执行环境时,再打个离开环境的标记,在下一个回收周期内,会将离开执行环境的变量进行回收

2. 引用计数:

当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。

相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。如:

代码语言:javascript
复制
function fn() {
    var q = {}; // q 指向对象的引用次数为 1
    var a = q;  // q 指向对象的引用次数加 1,为 2
    var c = q;  // q 指向对象的引用次数再加 1,为 3
    var a = {}; // q 指向对象的引用次数减 1,为 2
}

这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为 0 的值所占用的内存,进而无法刚问引用次数为0的变量。

但该方式会存在一个bug,即循环引用的变量不会被回收,如:

代码语言:javascript
复制
function fn() {
    var q = {};  // q 指向对象的引用次数为 1
    var a = {};  // a 指向对象的引用次数为 1
    q.obj = a;  // a 指向对象的引用次数为 2
    a.obj = q;  // q 指向对象的引用次数为 2
}
fn();

即使fn已经执行完毕,理论上q和a应该会被回收,但由于引用次数不为0,就造成了不会被回收

四、哪些场景会造成内存泄露

  • 不合理使用闭包,内部有外部变量引用的话,那么这个变量就一直在内存中无法回收
  • 不合理使用定时器,已结束使用定时器,但未取消,且定时器内部有外部变量引用的话,那么这个变量就一直在内存中无法回收
  • 不合理获取DOM元素,DOM已经被删除,且程序一直保存该DOM的引用,导致无法被回收

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档