基础概念
闭包是指有权访问另一个函数作用域中的变量的函数。
一般来说,函数内部可以访问函数外部的全局变量
var a = 1;//全局变量
function f1(){
alert(a);
}
f1();//1
函数外部不能访问函数内部的局部变量
function f2(){
var a = 1 ; //局部变量
}
alert(a); //error
注意,在函数内部定义变量时,要加上var,否则该变量就是全局变量了
function f3(){
a = 1 ; //全局变量
}
alert(a); //1
但是,有时候我们想得到函数内部的局部变量,那应该如何实现呢?这就引入了闭包的概念。
function f1(){
var n =1;
return function(){
alert(n)
}
result = f1(); result();//1
变量的一生:
JS里面有两种变量,一种是全局变量,一种是局部变量。局部变量是个依附着所属空间的东西,一旦所属空间没有,它也就消失了。而全局变量,它的生命周期就是js文件使用的周期。
所以如果你要销毁变量,如果是全局变量,那么你需要覆盖它,如果是局部变量你只要等待它所在的方法结束,它就自动销毁了。
function test(){var a=3;}
alert(a); //error,a 已经被销毁了
for(var a=3;a<10;a++){}
alert(a); // 输出10,因为a在全局中定义,还没有被销毁
但闭包是一种特殊的情况。闭包中的变量,这个函数的空间将会一直在内存中保留。
function test(){
var a=3;
return function(){
return a;
}
}
b=test();
外部没法输出a,这是因为没法访问,但a还是存在于内存之中。因为内部的函数引用了外部的变量a
闭包的作用
1、读取函数内部的变量
就如上面闭包的例子,可以在函数外部读取函数内部的变量。
2、将变量的值始终保存在内存中
一般来讲,当函数执行完毕之后,函数内部的局部活动对象就会被销毁,内存中仅保存全局作用域,即js的内存回收机制。
如果这个函数内部又嵌套了另一个函数,而这个函数是有可能在外部被调用到的.并且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题。如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要的外部函数中变量的值了.所以js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收。
注意事项
1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。