文章目录

  • 一、是什么
  • 二、垃圾回收机制
    • 标记清除
    • 引用计数
    • 小结
  • 三、常见内存泄露情况
  • 参考文献

一、是什么

内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存

并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费

程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存

对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃

C语言中,因为是手动管理内存,内存泄露是经常出现的事情。

char * buffer;
buffer = (char*) malloc(42);// Do something with bufferfree(buffer);

上面是 C 语言代码,malloc方法用来申请内存,使用完毕之后,必须自己用free方法释放内存。

这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这被称为"垃圾回收机制"

二、垃圾回收机制

Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存

原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存

通常情况下有两种实现方式:

  • 标记清除
  • 引用计数

标记清除

JavaScript最常用的垃圾收回机制

当变量进入执行环境是,就标记这个变量为“进入环境“。进入环境的变量所占用的内存就不能释放,当变量离开环境时,则将其标记为“离开环境“

垃圾回收程序运行的时候,会标记内存中存储的所有变量。然后,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉

在此之后再被加上标记的变量就是待删除的了,原因是任何在上下文中的变量都访问不到它们了

随后垃圾回收程序做一次内存清理,销毁带标记的所有值并收回它们的内存

举个例子:

var m = 0,n = 19 // 把 m,n,add() 标记为进入环境。
add(m, n) // 把 a, b, c标记为进入环境。
console.log(n) // a,b,c标记为离开环境,等待垃圾回收。
function add(a, b) {a++var c = a + breturn c
}

引用计数

语言引擎有一张"引用表",保存了内存里面所有的资源(通常是各种值)的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放

如果一个值不再需要了,引用数却不为0,垃圾回收机制无法释放这块内存,从而导致内存泄漏

const arr = [1, 2, 3, 4];
console.log('hello world');

上面代码中,数组[1, 2, 3, 4]是一个值,会占用内存。变量arr是仅有的对这个值的引用,因此引用次数为1。尽管后面的代码没有用到arr,它还是会持续占用内存

如果需要这块内存被垃圾回收机制释放,只需要设置如下:

arr = null

通过设置arrnull,就解除了对数组[1,2,3,4]的引用,引用次数变为 0,就被垃圾回收了

小结

有了垃圾回收机制,不代表不用关注内存泄露。那些很占空间的值,一旦不再用到,需要检查是否还存在对它们的引用。如果是的话,就必须手动解除引用

三、常见内存泄露情况

意外的全局变量

function foo(arg) {bar = "this is a hidden global variable";
}

另一种意外的全局变量可能由 this 创建:

function foo() {this.variable = "potential accidental global";
}
// foo 调用自己,this 指向了全局对象(window)
foo();

上述使用严格模式,可以避免意外的全局变量

定时器也常会造成内存泄露

var someResource = getData();
setInterval(function() {var node = document.getElementById('Node');if(node) {// 处理 node 和 someResourcenode.innerHTML = JSON.stringify(someResource));}
}, 1000);

如果id为Node的元素从DOM中移除,该定时器仍会存在,同时,因为回调函数中包含对someResource的引用,定时器外面的someResource也不会被释放

包括我们之前所说的闭包,维持函数内局部变量,使其得不到释放

function bindEvent() {var obj = document.createElement('XXX');var unused = function () {console.log(obj, '闭包内引用obj obj不会被释放');};obj = null; // 解决方法
}

没有清理对DOM元素的引用同样造成内存泄露

const refA = document.getElementById('refA');
document.body.removeChild(refA); // dom删除了
console.log(refA, 'refA'); // 但是还存在引用能console出整个div 没有被回收
refA = null;
console.log(refA, 'refA'); // 解除引用

包括使用事件监听addEventListener监听的时候,在不监听的情况下使用removeEventListener取消对事件监听

参考文献

  • http://www.ruanyifeng.com/blog/2017/04/memory-leak.html
  • https://zh.wikipedia.org/wiki

【JavaScript】js中内存泄漏的几种情况?相关推荐

  1. js中内存泄漏的几种情况

    内存泄漏:由于疏忽或错误造成程序未能释放已经不再使用的内存 1)意外的全局变量 解决方法:严格模式进行检测 例:函数内部定义全局变量(直接赋值) 2)定时器 不用的时候,及时清除定时器 没油及时清除的 ...

  2. JavaScript 中内存泄漏的几种情况

    内存泄露是什么 内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存 并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段 ...

  3. 内存泄漏的8种情况(附代码示例)

    一. 内存泄漏(memroy leak)         严格来说,只有对象不会再被程序用到了,但是GC又不能回收它们的情况,才叫内存泄漏         宽泛的讲,实际情况中很多时候一些不太好的实践 ...

  4. JS 内存泄漏的几种情况以及解决方案

    内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存 并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了 ...

  5. JavaScript内存泄漏的几种情况

    不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak). 意外的全局变量 原因:全局变量,不会被回收. 解决:使用严格模式避免. 函数中不使用var声明变量,则会将变量作为全局变量创建 ...

  6. js中内存泄漏与内存溢出

    内存泄漏: 占用的内存没有及时的释放从而失去控制,从而造成内存的浪费.内存泄漏多了就容易引发内存溢出. 常见的造成内存泄漏的原因: (1)没有清除闭包 // 函数执行完后, 函数内的局部变量没有释放, ...

  7. C++内存泄漏的几种情况

    1.堆内存泄漏:new/mallc分配内存,未使用对应的delete/free回收 2.系统资源泄漏, Bitmap, handle,socket等资源未释放 3.没有将基类析构函数定义称为虚函数,( ...

  8. js中三元运算符的两种情况

    一.一般情况 <script type="text/javascript"> var b=5; (b == 5) ? a="true" : a=&q ...

  9. C++中内存泄漏,内存溢出区别及检查方法

    https://www.csdn.net/gather_2b/NtDakgzsMTEtYmxvZwO0O0OO0O0O.html c/c++中内存泄露和内存溢出的区别 内存泄漏的几种情况: 1. 在类 ...

最新文章

  1. 程序员新手 0年份等级 指导(一) 开发人员IT架构总览
  2. 网站防火墙探测工具Wafw00f
  3. 刚刚,旷视开源深度学习框架「天元」:Brain++内核,研发和落地都在用;孙剑:COCO三连冠背后的秘密武器...
  4. PAT甲级1139 First Contact (30 分):[C++题解] 图论、暴力枚举两个点、hash映射
  5. JSONObject和JSONArray的关系
  6. unity中实现简单对象池,附教程原理
  7. 第二十四天 多维数组
  8. 添加谷歌账户显示与服务器,解决添加google同步帐户出错竟然可以这般简单!
  9. 学计算机信息管理专业的感谢,2014年计算机信息管理专业自荐信
  10. 电脑网线,电脑网线主要分类
  11. BATT入局,小程序成超级APP连接一切的枢纽
  12. Java--静态代理和动态代理
  13. uni-app的h5/小程序/app 网络请求,解决本地环境和生产环境网络请求问题
  14. jar a java exception has occured_Java Virtual Machine报错:A Java Exception has occured
  15. lan9252、lan9253和lan9254参数比较
  16. Zxing扫描条形码后得到结果前面多了一个0的问题
  17. 【基础算法训练】—— 栈
  18. 你对区块链的理解还停留在炒币上吗
  19. 【案例分析】服务器数据恢复
  20. 2.5野兔和山猫的种群动态变化

热门文章

  1. 计算机和科学有关系吗,软件测试和计算机科学没有很大关系
  2. 使用 .NET WinForm 开发所见即所得的 IDE 开发环境,实现不写代码直接生成应用程序
  3. Android开发之锁屏显示Activity
  4. java中怎么调用邮箱自动回信息_使用java发送短信和邮件
  5. List集合的五种遍历方式
  6. java感谢地说说_感谢感慨心酸的句子说说心情
  7. word内容无法复制
  8. 写带有代码博客的小技巧
  9. O(logn)在两个有序数组找第k小的数
  10. Java Web学习总结(38)——JavaWeb网站架构设计总结