JavaScript中的闭包是一个重要概念,在一些复杂编程中(比如写插件),经常会用到。
闭包的概念并不复杂,但是有一点绕。
闭包主要是要解决私有变量不能被其作用域外部访问的问题。
一个闭包一般有三个主体函数:宿主函数(父体函数),闭包函数(子体函数),调用函数(外部函数)。
宿主函数一般功能为初始化私有变量,如计数器等。并返回闭包函数。
闭包函数的功能是操作私有变量,并返回操作结果。
调用函数的功能是调用闭包函数。但会执行一次宿主函数以完成初始化。
下面创建一个闭包来说明一下。
<pre name="code" class="javascript"> count=50; //设置比较用的全局变量
/*闭包*/
function fn1(){ //函数1,做为闭包的父体。
var count=10; //父体函数代码。
console.log('父体函数中='+count); //观察父体执行次数。
return function fn2(){ //函数2,做为闭包的子体。同时做为父体函数1的返回值。
console.log('子体函数中='+count); //观察子体函数执行次数。
return count+=1; //子体函数代码。返回目标值。
}
}
var fn3=fn1(); //将函数1执行一次,并将返回值赋值给cd
console.log(fn3); //观察cd的内容。
fn3(); //持续观察cd的执行结果。
fn3();
fn3();
fn3();
a=fn3()+6; //将结果参与运算
console.log('参与运算--结果+6='+a);
控制台输出:
父体函数中=10
function fn2()
子体函数中=10
子体函数中=11
子体函数中=12
子体函数中=13
子体函数中=14
参与运算--结果+6=21
上面这个函数中,
1、先设置一个全局变量count=50,做为比较。
2、写一个函数fn1。fn1中设置一个私有变量count=10。
3、然后返回一个函数,返回函数一般可写做匿名函数,为标识方便,这里加一个名字fn2。
4、fn2函数里操作count的值,每执行一次,count的值加1,并返回结果。
5、声明一个fn3, 并将fn1()的返回值赋值给fn3。这里注意,是函数fn1执行一次的返回值,并非其函数本身。
6、控制台输出fn3,可发现其实它就是fn2。
7、运行fn3,共五次,发现其是基于count=10在变化,而非全局变量count=50。
8、fn3的返回值可以直接参与其它表达式运算。
综上,可以发现,闭包其实就是将一个函数体内的函数移植到函数体外执行。
那么闭包的作用域是发生了什么变化?
关于JavaScript的函数作用域,一句话概括之,即:你生在哪儿不重要,重要的是哪儿调用了你。
详情会在另一篇博文内说明。