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