一、什么是内存泄露
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。在C++中,因为是手动管理内存,内存泄露是经常出现的事情。而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使用的情况下几乎不会发生内存泄露。浏览器中也是采用自动垃圾回收方法管理内存,但由于浏览器垃圾回收方法有bug,会产生内存泄露。
二、引起垃圾收集语言内存泄露的主要原因是不必要的引用。
三、内存泄露的几种情况
1.意外的全局变量
体现 JavaScript 宽容性的一点表现在它处理未声明变量的方式上:一个未声明变量的引用会在全局对象中创建一个新的变量。在浏览器的环境下,全局对象就是 window,也就是说:
functionfoo(arg){
bar="this is a hidden global variable";
}
实际上是:
functionfoo(arg){
window.bar="this is an explicit global variable";
}
如果 bar 是一个应该指向 foo 函数作用域内变量的引用,但是你忘记使用 var 来声明这个变量,这时一个全局变量就会被创建出来。在这个例子中,一个简单的字符串泄露并不会造成很大的危害,但这无疑是错误的。
function bindEvent()
{
var obj=document.createElement("XXX");
obj.οnclick=function(){
//Even if it's a empty function
}
}
function bindEvent()
{
var obj=document.createElement("XXX");
obj.οnclick=onclickHandler;
}
function onclickHandler(){
//do something
}
或者在定义事件处理函数的外部函数中,删除对dom的引用
function bindEvent()
{
var obj=document.createElement("XXX");
obj.οnclick=function(){
//Even if it's a empty function
}
obj=null;
}
3.没有清理的DOM元素的引用
即当页面中元素被移除或替换时,若元素绑定的事件仍没被移除,在IE中不会作出恰当处理,此时要先手工移除事件,不然会存在内存泄露。
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"> </div> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.onclick = function(){ document.getElementById("myDiv").innerHTML = "Processing..."; } </script>
应改成下面
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"> </div> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.onclick = function(){ btn.onclick = null; document.getElementById("myDiv").innerHTML = "Processing..."; } </script>
或者采用事件委托
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"> </div> <script type="text/javascript"> document.onclick = function(event){ event = event || window.event; if(event.target.id == "myBtn"){ document.getElementById("myDiv").innerHTML = "Processing..."; } } </script>
<script type="text/javascript">
var someResource = getData(){
setInterval(function(){
var node = document.getElementById('Node');
if (node)
{
node.innerHTML = JSON.stringify(someResource);
}
},1000);
}
</script>
5.自动类型装箱转换(IE6,IE7)
var s="hhhhh";
alert(s.length);
"hhhhh"已经泄露了,关键问题出在s.length上,在js类型中,String类型并非对象,但是可以可以使用(.)运算符,因为js的默认类型转换机制,允许js在遇到(.)运算符时,自动将string类型转换为Object中对应的String对象。该临时转换的对象100%会泄露。
应改为
var s="lalala";
alert(new String(s).length);
1.减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收
2.注意程序逻辑,避免“死循环”之类的
3.避免创建过多的对象
原则:不用了的东西要及时归还。
二.内存泄露的一些疑问
1、内存泄露是内存占用很大吗?
不是,即使是1byte的内存,也叫内存泄露。
2、程序中提示内存不足,是内存泄露吗?
不是,着一般是无限递归函数调用,导致栈内存溢出。
3.内存泄露是哪个区域?
堆区。栈区不会泄露
4.window对象时DOM对象吗?
不是,window对象参与的循环引用是不会内存泄露。
5.内存泄露的后果?
大多数情况下,后果不是很严重。但是过多的DOM操作会使网页执行速度变慢。
6.跳转网页,内存泄露仍然存在吗?
仍然存在,直到浏览器关闭。