内存泄漏
在程序中,当声明变量、定义函数的时候都会使用内存。那些程序用不到,没有予以释放的内存,就造成内存泄漏.(memory leak)
垃圾回收
- 引用计数
跟踪记录每个值被引用的次数;将一个引用类型给一个变量赋值时,这个值的引用次数就变成了1,同一个值为引用次数为0时,就可以被回收 - 标记清除
垃圾收集器给存储在内存的变量加上标记,然后去掉环境中的变量以及被引用变量的标记。
JavaScript中的内存泄漏
1.循环引用造成的内存泄漏
两个对象互相引用,由于他们互相引用至少一次,所以不会被回收
<html>
<body>
<script type="text/javascript">
document.write("Circular references between JavaScript and DOM!");
var obj;
window.onload = function(){
obj=document.getElementById("DivElement");
document.getElementById("DivElement").expandoProperty=obj;
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
};
</script>
<div id="DivElement">Div Element</div>
</body>
</html>
2.调用外部方法造成的内存泄漏
声明一个全局变量,this指window对象,会被window引用,所以不会被内存回收
<html>
<head>
<script type="text/javascript">
function myFunction(element) {
this.elementReference = element;
// This code forms a circular reference he//by DOM-->JS-->DOM
element.expandoProperty = this;
}
function Leak() {
//This code will leak
new myFunction(document.getElementById("myDiv"));
}
</script>
</head>
<body onload="Leak()">
<div id="myDiv"></div>
</body>
</html>
3.事件处理器造成的内存泄漏
obj包含了对dom对象#element的引用,反过来说dom对象也包含了对obj的引用,
他们相互引用就造成了内存泄漏
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
};
</script>
<button id="element">Click Me</button>
</body>
</html>
JavaScript中的闭包
内部函数
function parentFunction(paramA)
{
var a = paramA;
function childFunction()
{
return a + 2;
}
return childFunction();
}
简单的闭包
<html>
<body>
<script type="text/javascript">
window.onload= function closureDemoParentFunction(paramA)
{
var a = paramA;
return function closureDemoInnerFunction (paramB)
{
alert( a +" "+ paramB);
};
};
var x = closureDemoParentFunction("outer x");
x("inner x");
</script>
</body>
</html>
如何避免内存泄漏
1.终止循环引用
<html>
<body>
<script type="text/javascript">
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction()
{
alert("Hi! I have avoided the leak");
// Some logic here
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
obj = null; //This breaks the circular reference
};
</script>
<button id="element">"Click Here"</button>
</body>
</html>
2.添加另一种闭包
<html>
<body>
<script type="text/javascript">
window.onload=function outerFunction(){
var anotherObj = function innerFunction()
{
// Some logic here
alert("Hi! I have avoided the leak");
};
(function anotherInnerFunction(){
var obj = document.getElementById("element");
obj.onclick=anotherObj }
)();
};
</script>
<button id="element">"Click Here"</button>
</body>
</html>
3.避免使用闭包
<html>
<head>
<script type="text/javascript">
window.onload=function()
{
var obj = document.getElementById("element");
obj.onclick = doesNotLeak;
}
function doesNotLeak()
{
//Your Logic here
alert("Hi! I have avoided the leak");
}
</script>
</head>
<body>
<button id="element">"Click Here"</button>
</body>
</html>
说明
文章参考IBM article on “Memory leak patterns in JavaScript” (2007)