1. 闭包的概念
据我们所知,局部变量在函数退出之后就不占据内存空间,但存在一种特殊的函数,能使局部变量在函数退出之后继续占据内存,为外部函数所调用,这个特殊的函数就是闭包。那么闭包是怎么做到将局部函数一直占据内存的呢?看看下面的例子。
function a(){
var Aitem=2;//定义局部变量item
function b() { //定义内部函数b()
alert(Aitem);
}
b();
}
a();//结果是2
2. 闭包的机理
从上可以看出内部函数可以读取外部函数的局部变量。此时的内部函数的作用域仅限于外部函数a(),只有通过调用外部函数a()才可以运行内部函数b()。当外部函数执行结束,内部函数的内存也将清除。但是如果我们将内部函数赋给一个全局变量,那么内部函数将从局部变量转化成全局变量。即使外部函数退出了,作为全局变量的内部函数也将保存在内存中。那么如何让内部函数成为全局变量呢?
function a(x){
var Aitem=2;//定义局部变量item
return function b(y) { //a函数结果返回一个b函数
alert(x+y+(++Aitem));
}
}
var closure=a(1);//将a(1)return的结果b()赋给全局变量,closure=b(y){ alert(1+y+(++Aitem))}
closure(1);//弹出5;closure(1)=b(y){ alert(1+1+(++2))}
closure(1);//弹出6;closure(1)=b(y){ alert(1+1+(++3))}
上例中的closure()函数即闭包。第一次closure(1)中Aitem=2,第二次closure(1)中Aitem=3,可以看出item这个局部变量在a()退出以后并没有被清除,而是像一个全局变量一样一直保存在内存中。这就是闭包的神奇所在。closure()闭包依赖于b(y),而b(y)又是a(x)的局部函数,故closure()闭包可以实时访问a(x)的局部变量。如果没有将内部函数装化成全局变量的话,就形不成闭包,请看下面的例子:
function a(x){
var Aitem=2;//定义局部变量item
function b(y) { //定义局部函数b
alert(x+y+(++Aitem));
}
b(1);//在a()内部运行b(1);即alert(x+1+(++2))
}
a(1);//弹出5;即alert(1+1+(++2))
上例没有将局部函数b()赋给全局变量,在a(1)运行以后b()就不复存在,Aitem也无从获取。
3. 总结
闭包是可以读取其他函数内部变量的函数,是外部函数和内部函数的一座桥梁。
闭包拥有两个作用:
- 使局部变量keep alive
- 读取其他函数的局部变量
闭包的缺点:
- 常驻内存,造成内存的浪费