1.什么是闭包
先看下面的小例子:
function a(){
var n = 0;
function inc(){
n++;
console.log(n);
}
return inc;
}
var c = a();
c(); //控制台输出1
c(); //控制台输出2
分析下这段代码是怎么执行的:
var c = a ();这句a()返回的是函数inc,所以这句话等同于 var c = inc; 而c();等同于 inc ();(注意:函数名只是一个标识,在c语言中指的是指向函数的指针,而加上'()'才是调用函数),所以后面三句翻译过来就是 var c=inc; inc(); inc();------- 这就是闭包。
不同的资料对闭包的解释有不同的见解,其实意思都是一样的,那就是不好理解。小编在这里给出我的理解,让大家一下就能够明白:
满足一下两个条件的就是闭包:
①函数嵌套函数
②内部函数能够使用外部函数的参数或者变量
2.为什么需要闭包?何时使用?
局部变量无法共享和长久的保存,而全局变量可能造成变量的污染,所以,我们希望能够有一种机制,既可以长久的保存变量,又不会造成污染。因此,如果我们既想反复使用变量,又想避免全局污染,这时就用闭包
3.如何使用
①定义外层函数,封装被保护的局部变量
②定义内层函数,执行对外部函数变量的操作
③外层函数返回内层函数的对象,并且调用外层函数,结果保存在一个全局变量中
4.闭包的作用
Ⅰ.提高局部变量的生存周期
我们都知道,全局变量的生存周期是永久的,一直到我们主动去销毁,而在函数内声明的局部变量来说,当函数结束时,这些函数变量立即失去他们的价值,也就被垃圾回收机制销毁了。可在闭包中,并不是这样滴。下面用代码说话,比较直观:
function demo(){
var a=1;
a++;
console.log(a);
}
demo();//2
demo();//2
demo();//还是2
上面情况的变量直接被销毁
下面看看另一种方式:
function demo(){
var a=1;
return function(){
a++;
console.log(a);
}
}
var c=demo();
c();//2
c();//3
c();//4
这种变量并没有销毁,而是一直在使用
上面两种情况对比发现,当退出函数后,使用闭包中的变量没有立即消失,而是一直存在,这样在第二次调用 a 时才会在 2 的基础上加 1 ,依次类推,这就说明变量a一直存在,生存周期加长。
Ⅱ.封装
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var liList=document.getElementsByTagName('li');
for(var i = 0; i < liList.length; i++ ){
liList[i].onclick=function(){
console.log(i);
}
}
</script>
测试这段代码,无论点击哪个 li ,输出的都是 5 ,这是因为当事件被触发时,for循环早就已经结束 ,所以 i 变量的值是 5 。
解决其实挺简单,用封装的思想把 i 的值封装起来,等到用到的时候会找到封装在闭包环境中的 i
代码如下:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var liList=document.getElementsByTagName('li');
for(var i = 0; i < liList.length; i++ ){
liList[i].onclick=(function(i){
return function (){
console.log(i);
}
})(i);
}
</script>
5.小结
闭包的用途还有很多,其他的功能还需要读者自己去发现,去总结。 小编能力有限,暂时分享这么多,希望读者在后面的学习中继续深挖其中的用途,有哪些大神可以指点一下小编。