闭包概念
声明在一个函数里的函数叫闭包.在闭包的内部可以访问其外部函数里定义的局部变量.
闭包的两个作用:
1.可以通过闭包获取函数内的局部变量.
2.通过闭包可以保证局部变量的生命周期与整个网页的生命周期一样.
function t1(){
var age = 20;
function t2(){
alert(age);
}
return t2;
}
var tmp = t1();
var age = 99;
tmp();//20
在大部分的语言中,t1被调用执行,则申请内存,并把局部变量push入栈。
t1函数执行完毕,内部的局部变量随着函数的退出而销毁。因此,age = 20这个局部变量就消失了。
但是在js中,age = 20这个变量却被t2捕捉,
即使t1执行完毕,通过t2依然能够访问该变量。
这种情况返回的函数,并非孤立的函数,甚至把其周围的变量环境,形成了封闭的“环境包”,共同返回,所以叫闭包。
概括:函数的作用域取决于声明时,而不取决于调用时。
闭包的应用-闭包计数器
多个人开发js程序,需要一个全局计数器,多个人的函数共同用一个计数器,计数器一直增长
解决办法:
设立一个全局变量,window.cnt = 0;
调用:++window.cnt;
这个方法可行,但是应该避免过多的使用全局变量,防止全局变量被污染。
当你引用其他人的js程序时,如果他的程序内也有一个全局变量window.cnt = 'hello';
那么你的全局变量就会被无情的改变了。
那么可以考虑使用闭包维护一个别人污染不到的变量,做计数器。
function counter(){
var cnt = 0;//当counter执行完毕后,除了返回的cnter函数谁也访问不到cnt变量了
var cnter = function (){
return ++cnt;
}
return cnter;
}
var inc = counter();
alert(inc());
alert(inc());
alert(inc());
// 但是还是产生了2个变量,counter和inc
简化版本:
var cnt = (function (){
var cnt = 0;
return function(){
return ++cnt;
}
})();
alert(cnt());
alert(cnt());
// cnt 不依然是全局变量吗?
那么在工作中,该如何避免全局变量的污染。
1:统一放在一个全局对象上,如:jquery ->$
2:每人用自己的命名空间。
jquery的计数器插件形式
$ = {};
$.cnt = (function (){
var cnt = 0;
return function(){
return ++cnt;
}
})();
alert($.cnt());
2.个人命名空间,在团队开发中也很常见。
var YK = {};
YK.cnt = (function (){
var cnt = 0;
return function(){
return ++cnt;
}
})();
alert(YK.cnt());
闭包练习题
<ul>
<li>春</li>
<li>夏</li>
<li>秋</li>
<li>冬</li>
</ul>
<script type="text/javascript">
// 要求:点击li分别弹出 0 1 2 3
window.onload=function(){
var lis=document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
lis[i].onclick=function(i){
return function(){alert(i)};
//return alert(i);为什么这么写不可以?
}(i);
}
}
</script>