admin 管理员组

文章数量: 887021

那些操作会造成内存泄露,解决方法

JS常见的内存泄漏及可用的解决方法

内存泄漏?
官方解释:内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
通俗点就是指由于疏忽或者错误造成程序未能释放已经不再使用的内存,不再用到的内存却没有及时释放,从而造成内存上的浪费。

1.闭包

闭包可以维持函数内局部变量,使其得不到释放。

function assignHandler(){var element = document.getElementById("someElement");element.onclick = function(){alert(element.id);};
}

解决:将事件处理函数定义在外部
tips:闭包在IE6下会造成内存泄漏,但是现在已经无须考虑了。值得注意的是闭包本身不会造成内存泄漏,但闭包过多很容易导致内存泄漏。闭包会造成对象引用的生命周期脱离当前函数的上下文,如果闭包如果使用不当,可以导致环形引用(circular reference),类似于死锁,只能避免,无法发生之后解决,即使有垃圾回收也还是会内存泄露。

2.意外的全局变量引起的内存泄露
function fn(){	a = "123"; //a成为一个全局变量,不会被回收
}
// 上面的写法等价于
function fn() {window.a = '123'
}function fn() {this.a = 'test'// 函数自身发生调用,this指向全局对象window
}
foo();

上面的a变量应该是foo()内部作用域变量的引用,由于没有使用var来声明这个变量,这时变量a就被创建成了全局变量,这个就是错误的,会导致内存泄漏。
解决方式: 在js文件开头添加 ‘use strict’,开启严格模式。(或者一般将使用过后的全局变量设置为 null 或者将它重新赋值,这个会涉及的缓存的问题,需要注意)

<script> 
"use strict"; 
console.log("这是严格模式。"); 
</script> 
<script> console.log("这是正常模式。"); 
</script> 
3.未清理的DOM元素引用
var a = document.getElementById('id');
document.body.removeChild(a);

不能回收,因为存在变量a对它的引用。虽然我们用removeChild移除了,但是还在对象里保存着#的引用,即DOM元素还在内存里面。
解决方法: a = null;

4.被遗忘的定时器或者回调

var someResouce=getData();
setInterval( function(){
var node= document.getElementById( 'Node');
if(node){
node.innerHTML= JSON.stringify(someResouce)
}
}, 1000)
//这样的代码很常见, 如果 id 为 Node 的元素从 DOM 中移除, 该定时器仍会存在, 同时, 因为回调函数中包含对 someResource 的引用, 定时器外面的 someResource 也不会被释放。

定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就会造成内存泄漏。
**解决方式:**当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout

5. console

控制台日志记录对总体内存内置文件的影响,也是个重大的问题,同时也是容易被忽略的。记录错误的对象,可以将大量的数据保留在内存中。传递给console.log的对象是不能被垃圾回收,所以没有去掉console.log可能会存在内存泄漏~~~~

6、怎样避免内存泄露

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

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

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

本文标签: 那些操作会造成内存泄露 解决方法