以前只听说过闭包(closure),并没有深入研究过,今天来仔细看一看闭包究竟是个什么东西。
1.认识闭包
闭包:是一个有权访问另一个函数作用域中的变量的函数。通常创建的方法是在一个函数内创建另一个函数,是该函数可以访问其局部变量。
优点:可以使函数的局部变量被保存在内存中,不被js垃圾回收器销毁。避免全局变量被污染。正常情况下,局部变量在函数执行完成后会被销毁,而闭包可以使该变量不被销毁。
缺点:闭包会常住内存,对内存消耗大,容易造成内存溢出,在IE上更易崩溃。可在使用完后使对象等于null来清空对象。
2.了解作用链
作用链:js中所有的变量都是对象的一个属性,而该对象可能也是另一个对象的属性,但所有对象都是window对象的属性,那么他们之间的关系就形成了一个链式,即是作用链。
作用域:是js变量的生命活动范围,超出该范围将会被GC销毁。
注意:在js中没有用var声明的变量是全局变量,且是window对象的属性,有var声明的变量才是局部变量,归函数所有。
3.闭包的特性
a.闭包是一个嵌套在函数中的函数。
b.函数内部可以引用外部函数的参数和变量。
c.闭包的参数和变量不会被垃圾回收机制回收。
(垃圾回收机制:回收不被引用的对象;回收2个互相引用而不被第3者引用的对象)
4.实例分析
<script type="text/javascript">
var a = [];
function testa(){
var i= 0;
for (;i<3;i=i+1){
a[i]=function(){
alert(i);
};
}
}
testa();
a[0]();//3
a[1]();//3
a[2]();//3
</script>
上诉代码对数组a使用了闭包结构,i变量确实被存储了,但是却全部变成了3,这是因为闭包中所存储的变量并不是变量的值,而是闭包的一个引用,当testa方法执行完成后,i变量已经成为了3,之后在引用i时,只会是3.那么如何存储所有变量呢,我们可以让内部函数在循环创建的时候立即执行,并且捕捉当前的索引值,然后记录在自己的一个本地变量里.然后利用返回函数的方法,重写内部函数,让下一次调用的时候,返回本地变量的值,例如:
<script type="text/javascript">
var a = [];
function testa(){
var i= 0;
for (;i<3;i=i+1){
a[i]=(function(i){//立即执行当前方法
return function(){//重写返回方法
alert(i);
};
})(i);//记录i的当前值
}
}
testa();
a[0]();//0
a[1]();//1
a[2]();//2
</script>
这里的return是一个闭包函数。