在编程技术中,闭包应该属于较高级的技术了。
当使用回调函数时,通常会涉及到一些上下文的传递。在c/c++等语言中,会使用全局变量或堆内存来传递上下文。全局变量的缺点很明显,而堆内存又很容易发生内存泄漏。而在更高级的脚本语言(如javascript),可以通过闭包技术来轻松的完成上下文传递。
1、闭包的概念
官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
实例代码如下:
var external = (function (x) {
var num = 5 ;
return function (y) {
return x + y + (++num);
}
});
var intrinsic = external(2);
intrinsic(4) //返回12
intrinsic(4) //返回13
intrinsic(4) //返回14
intrinsic(5) //返回16
var intrinsic2 = external(2);
intrinsic2(4) //返回12
intrinsic2(4) //返回13
intrinsic2(4) //返回14
intrinsic2(5) //返回16
2、 闭包的特点
作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
3、 闭包的用途
读取函数内部的变量。
把这些变量的值始终保持在内存中。
4、 闭包的优点:
逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
方便调用上下文的局部变量。
加强封装性,第2点的延伸,可以达到对变量的保护作用。
5、使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
实例代码如下:
var array = [];
function external() {
var intrinsic = function(){
}
array.push(intrinsic);
return intrinsic;
}
for(var i = 0 ; i < 10000; i ++){
external();
}
alert(array[0] == array[1]); //返回true
通过上面的测试我们会看到这一万次external()执行所产生的同一个逻辑的闭包的地址并不相同,也就是说它生产了一堆的一模一样的Function对象,这样有好处就是可以以工厂模式产生函数以备使用,然而如果你的稍有不慎将闭包当做常态逻辑使用,就不可避免的会造成内存垃圾。