定义:函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回
function aaa(a){ //a,b都要在内部函数中被引用,所以不会被垃圾回收机制收回。 var b = 5; function bbb(){ alert(a); alert(b); } } aaa(); //JS中的垃圾回收机制 function aaa(){ var a = 1; } aaa(); //当函数执行完毕后,变量a就会被垃圾回收机制收回。 function aaa(){ var a = 5; function bbb(){ alert(a); } return bbb; } var c = aaa();//a已经执行完毕,c代表的就是bbb这个函数 c();//c执行的话变量其实并没有收回。
好处
1.希望一个变量长期驻扎在内存当中,例子见上
2.避免全局变量的污染
var a = 1;
function aaa(){
a++;
alert(a);
}
//aaa(); //2
//aaa(); //3
//alert(a);
//由于a是一个全局变量,所以在外部是能被访问到的。为了提高性能,尽量避免出现全局变量。
function aaa(){
var a = 1;
a++;
alert(a);
}
aaa(); //2
aaa(); //2
之所以弹出两次2,是因为当每一次调用时,代码都执行了一次,这样的话a就不会继续累加了。
如何做到既让a是一个局部变量,又要让a累加?这就是闭包所能做到的。
function aaa(){
var a = 1;
return function(){//这样就构成了一个函数嵌套函数的关系,而变量a相对于内部函数是可以被找到的,而且不受外部执行函数的影响,当它执行完毕后,函数依然可以调用函数a的变量,而且还会累加。
a++;
alert(a);
}
}
var b = aaa();
b(); //2
b(); //3
alert(a);//此时外部引用a就访问不到了。因为它是一个局部变量。
将函数声明改成函数表达式,
var aaa = (function(){//将一个匿名函数赋给变量aaa,这样函数运行时就会执行一次,
此时变量aaa就是外部函数执行完毕的返回值。
var a = 1;
return function(){
a++;
alert(a);
}
})();
aaa(); //2
aaa(); //3
通常将这种方式叫做代码模块化,防止全局变量的污染。
3.私有成员的存在
var aaa = (function(){ var a = 1; //局部变量,相对于下面私有方法是全局的 function bbb(){ //私有方法 a++; alert(a); } function ccc(){//私有方法 a++; alert(a); } return {//返回一个json的结构 b : bbb, c : ccc } })(); aaa.b(); //2 aaa.c(); //3 //alert(a); undefined //alert(bbb);undefined //alert(ccc);undefined
应用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link type="text/css" rel="stylesheet" href="css/style.css">
<script type="text/javascript">
window.οnlοad=function(){
var aLi = document.getElementsByTagName('li');
/*
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function(){//当点击时for循环已经结束了,所以每次点击都是3
alert(i);
}
};*/
//方法1 利用闭包的形式将值0123传进去,让它永远存在内存中,需要调用时直接来用
/*for (var i = 0; i < aLi.length; i++) {
(function(i){
aLi[i].onclick = function(){
alert(i);
}
})(i);
};*/
//当点击时,已经执行完毕,然后接着return一个返回值,返回一个匿名函数,
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = (function(i){ //i存在在内存中
return function(){
alert(i);//此处调用的i是存在在内存中的i
}
})(i);
};
}
</script>
</head>
<body>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</body>
</html>
闭包需要注意的地方。
在ie下会引发内存泄露。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link type="text/css" rel="stylesheet" href="css/style.css">
<script type="text/javascript">
/*window.onload = function(){
var oDiv = document.getElementById('div1');
oDiv.onclick = function(){
alert(oDiv.id);
};
window.onunload = function(){ //页面出来的时候把事件给取消掉
oDiv.onclick = null;
};
};*/
window.onload = function(){
var oDiv = document.getElementById('div1');
var id = oDiv.id; //提前赋给一个变量
oDiv.onclick = function(){
alert(id);//在里面去调用
};
oDiv = null; //接着让其为空
};
</script>
</head>
<body>
<div id="div1">aaa</div>
</body>
</html>