js内存泄漏几种方式及如何避免、内存溢出

一、什么是内存泄漏(memory leak)?

参考阮一峰老师博客:http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。

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

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

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

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

 二、JavaScript 的垃圾收集机制

JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入相应的环境,就可能用到它们。而当变量离开环境时,这将其 标记为“离开环境”。

常见内存泄漏的原因 :

1、全局变量引起的内存泄漏

function leaks(){  
    leak = 'xxxxxx';    //leak 成为一个全局变量,不会被回收
}

尤其当全局变量用于 临时存储和处理大量信息时,需要多加小心。如果必须使用全局变量存储大量数据时,确保用完以后把它设置为 null 或者重新定义。

与全局变量相关的增加内存消耗的一个主因是缓存。缓存数据是为了重用,缓存必须有一个大小上限才有用。高内存消耗导致缓存突破上限,因为缓 存内容无法被回收。

2、闭包引起的内存泄漏

闭包是 JavaScript 开发的一个关键方面:匿名函数可以访问父级作用域的变量。

var leaks = (function(){  
    var leak = 'xxxxxx';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
    }
})()

123456

 3、dom清空或删除时,事件未清除导致的内存泄漏

<div id="container"></div>

$('#container').bind('click', function(){
    console.log('click');
}).remove();

//导致内存泄漏
<div id="container"></div>

$('#container').bind('click', function(){
    console.log('click');
}).off('click').remove();

//把事件清除了,即可从内存中移除

子元素存在引用引起的内存泄漏:

假如你的 JavaScript 代码中保存了表格某一个 <td> 的引用。将来决定删除整个表格的时候,直觉认为 GC 会回收除了已保存的 <td> 以外的其它节点。

实际情况并非如此:此<td> 是表格的子节点,子元素与父元素是引用关系。由于代码保留了 <td> 的引用,导致整个表格仍待在内存中。

4、被遗忘的计时器或回调函数

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

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

怎样避免内存泄露:

1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

2)注意程序逻辑,避免“死循环”之类的 ;

3)避免创建过多的对象 原则:不用了的东西要及时归还。

三、什么是内存溢出(out of menory)? 

内存溢出(out of memory):程序要求的内存,超出了系统所能分配的范围

如:我们用一个int型4字节的数据来装一个float型8字节的数据,就会产生内存溢出。不过我们在编程是可以强制类型转换int XX = (int)float;只取float 4字节数据给int。

展开阅读全文

没有更多推荐了,返回首页