Closure
对于闭包(closure),我理解的就是函数内部使用函数,内部的函数就称为闭包。例如:
1 | funOut() { |
其中funIn()就称为funOut()函数的闭包,类似java中的内部类什么的。
Closure作用
每一种设计都有它的作用,如果闭包没有作用,恐怕也不会有人去研究它了。
作用1:进行回调
首先还是看一段nodejs代码:
1 | var fs = require("fs"); |
这是nodejs中的一个特性,叫做异步回调函数。本质上来说,所有的异步回调函数都是闭包。可以看以下的代码对比。
1 | fs.readFile('input.txt', function (err, data) { |
作用2:对于闭包(closure),当外部函数返回之后,内部函数依然可以访问外部函数的变量。
1 | function f1(){ |
代码中,外部函数f1只执行了一次,变量N设为0,并将内部函数f2赋值给了变量result。由于外部函数f1已经执行完毕,其内部变量N应该在内存中被清除,然而事实并不是这样:我们每次调用result的时候,发现变量N一直在内存中,并且在累加。为什么呢?这就是闭包的神奇之处了!
作用3 使用闭包定义私有变量
通常,JavaScript开发者使用下划线作为私有变量的前缀。但是实际上,这些变量依然可以被访问和修改,并非真正的私有变量。这时,使用闭包可以定义真正的私有变量:
1 | function Product() { |
代码中,对象p的的name属性为私有属性,使用p.name不能直接访问。
注意点
- 1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
参考资料
学习Javascript闭包(Closure)