《高级程序设计》上,这样说:当函数内部定义了其他函数的时候,就创建了闭包。闭包有权访问包含函数内部的所有变量。
简单说一下我的理解:
由于普通的函数执行之后,资源就会被回收、内存释放,如果需要保留其内部的变量,那么我们需要建立函数的闭包。
function a(){ var i = 0; function b(){ alert(i++); } return b; } var test = a(); test();
上面例子中,当函数a执行完并返回后,闭包使得JavaScript垃圾回收机制不会回收a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。
由于闭包的存在使得函数a返回后,a中的变量i始终存在,这样每次执行test(),都会弹出自加1之后的i。
另外闭包也可以实现封装,在person之外无法访问其内部的变量,而通过提供闭包的形式来访问,例子如下
var person = function(){ var name = "默认"; return{ "setName":function(newName){ name = newName; }, "getName":function(){ return name; } } }(); console.log(person.getName()); person.setName("李四"); console.log(person.getName());
闭包的另外一个重要用途是实现面向对象中的对象,传统的面向对象语言都有类的模板机制,这样不同的对象拥有独立的成员及状态,互不干涉。虽然JavaScript中没有类这样的机制,但是通过使用闭包,可以模拟出这样的机制,例子如下:
function Person(){ var name = "默认"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }; var john = Person(); console.log(john.getName()); john.setName("john"); console.log(john.getName()); var jack = Person(); console.log(jack.getName()); jack.setName("jack"); console.log(jack.getName());
以上例子中,john和jack都可以称为是Person这个类的实例,因为这两个实例对name这个成员的访问是独立的,互不影响的。
总结:
在函数内部定义子函数,这个子函数可以称为闭包,可以使用闭包来解决在函数外部如何访问函数内部变量的问题,实现父函数变量的保留。
通常如果不使用闭包,我们为了取值方便可能会将有些局部变量直接定义为全局变量,这样造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。有了函数的闭包也减少了对全局变量的使用,从而减少内存的占用。