首页
闭包
闭包
版权声明:本文为原创内容,转载请声明出处。
原文地址:http://www.excelib.com/article/233/show

闭包的概念

闭包是JavaScript中非常重要但又不太容易理解的一个概念,上一节我们讲了ES中变量是function级作用域,也就是说在function中定义的变量可以在function内部(包括内部定义的嵌套function中)使用,而在function外部是无法使用的,但是如果想办法在外部将function内部定义的嵌套function获取到不是就可以在外部使用function内部定义的局部变量了吗?这种用法就是闭包,我们来看个例子

1
2
3
4
5
6
7
8
9
function f1(){
     var v=1;
     function f2(){
         console.log(v);
     }
     return f2;
 }
 var f = f1();
 f();               // 1

这里在函数f1中定义了变量v,正常情况下在f1外面是无法访问v的,但是f1中嵌套定义的函数f2是可以访问到v的,而且在调用f1时会将函数f2返回出来,这样我们就可以在f1外部访问f1的局部变量v了,这就是闭包,当然,如果需要还可以在f2中直接返回v的值,这样就可以在f1外部获取到v的值了。

变量可长期保存

在使用闭包时需要注意,在保存返回函数的变量失效之前定义闭包的function会一直保存在内存中,比如下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
function f1(){
     var v=1;
     function f2(){
         console.log(v);
         v++;
     }
     return f2;
 }
 var f = f1();
 f();    //1
 f();    //2
 f();    //3

这里的f2函数在打印出v的值后又将v的值加了1,当我们连续调用f()时会在控制台依次打印出1,2,3,这说明f1函数一直在内存中保存着,这是因为我们保存f1返回嵌套函数f2的变量f是全局变量,他会一直保存在内存中,而f所指向的f2函数在执行时需要依赖f1,所以f1就会一直保存在内存中。这里需要注意f2本身因为没有被依赖,所以f2并不会一直保存在内存中,我们再来看个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function f1(){
     var v=1;
     function f2(){
         var v1 = 1;
         console.log(v,v1);
         v++;
         v1++;
     }
     return f2;
 }
 var f = f1();
 f();    //1 1
 f();    //2 1
 f();    //3 1

这里的v1是f2中的变量,他并不会长期保存在内存中,而是执行完之后就会销毁。

闭包的这种特性跟其他很多事情一样,不能简单地说好还是不好,而要看具体怎么去使用。有的人认为这种特性会导致内存无法释放而占用过多的内存,这也确实是他的弊端,不过如果使用得当的话也能带来很大的方便,比如我们可以使用这种变量来保存需要经过复杂运算的结果,这样就不需要每次都去运算,而是直接调用结果就可以了,再比如还可以使用它来保存初始化的参数等等。技术本身并没有好坏,关键是看我们怎么去使用。