闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在 Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby 和 Python,objective c 等语言中都能找到对闭包不同程度的支持。
闭包的价值在于可以作为函数对象 或者匿名函数,对于类型系统而言这就意味着不仅要表示数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中、作为参数传递给其他函数,最重要的是能够被函数动态地创建和返回。
举个简单的例子:
function a() {
var i = 0;
function b() {
alert(++i);
}
return b;
}
var c = a();
c(); //1
c(); //2
这段代码有两个特点:
(1)函数b嵌套在函数a内部;
(2)函数a返回函数b。
这样在执行完var c = a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。
这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。
匿名函数的例子:
jquery中我们经常用到这样的代码:
$("#id").click(
function(){
//do somethine
});
其中的function就是匿名函数。
匿名函数和闭包常常结合使用,是代码变得很灵活。
看一个插件的简单例子:
plugins=function(name){
var _name=name||'jack';
return {
nameWithAge:function(age){ alert(_name+"'s age is "+age); },
nameWithSex:function(sex){alert( _name+"'s sex is "+sex);}
};
}
ok,现在我要使用它了,
var myplugin=plugins('rose');
myplugin.nameWithAge(21);
输出结果:rose's age is 21
myplugin.nameWithSex('girl');
输出结果:rose's sex is girl
假如我现在有个新需求增加一个【爱好】的插件;那么你可以很灵活的扩充:
plugins=function(name){
var _name=name||'jack';
return {
nameWithAge:function(age){ alert(_name+"'s age is "+age); },
nameWithSex:function(sex){alert( _name+"'s sex is "+sex);},
nameWithHobby:function(hobby){alert(_name+"'s hobby is "+hobby);}
};
}
修改后调用插件:
myplugin.nameWithHobby('swiming');
输出结果:rose's hobby is swiming
可以看到闭包和匿名函数的结合体现了一定的灵活性。
以上只是自己的一点微不足道的经验,如果有什么不对的地方,欢迎大牛前来拍砖。