闭包是指有权访问另一个函数作用域中的变量的函数,通过通过在一个函数中创建的另一个函数而获得闭包。首先要说明的是,闭包并不等于匿名函数,匿名函数可以构成闭包,但不等于闭包。
闭包的作用域,曾一直是困扰我多天的问题。为什么在某些情况下,闭包只能访问到外部函数的活动对象?而在某些情况下,闭包能访问到整个作用域链上的每一个变量?具体的问题,要归结于闭包是否被引用。
当某个函数被调用时,会创建一个执行环境及相应的作用域链。
1、当内部函数是在外部函数被调用的期间被调用的,则可以享受整个作用域链,并且得到的变量值都是即时的。
var k= 0;
functioncreateFunctions() {
for (var i=0; i<10; i++) {
(function() {
alert(k);
k++;
}) (); //这里需要给内部函数加个模仿块级作用域处理,不然无法即时调用该函数。
};
}
createFunctions();
以上JS代码得到的结果是0~9。这说明了内部函数实时的调用了全局变量K并改变了它的值,同时能够实时的得出结果。
2、内部函数并非在外部函数被调用时执行,而是在外部函数结束后才执行。换句话说,内部函数是被引用的,而非被直接调用的。这时,内部函数只能调用外部函数的活动对象(即外部函数各变量的最终值)。
function createFunctions(){
var result =new Array();
for (vari=0; i < 5; i++) {
result[i] =function(){
return i;
};
/*在此,我们把函数赋值给数组result,并期待数组result返回i在每个时段的数值。但结果result的每一个值都是指向内部函数的指针。*/
}
returnresult;
}
var funcs =createFunctions();
/*在这里funcs得到了数组result的赋值。在使用funcs数组时,因为外部函数createFunctions已经结束了调用,因此只能留下自身的活动对象供以自身的内部函数调用。因此,funcs中的每一个值都是i的最终结果,即5*/
for(var i=0;i < funcs.length; i++){
document.write(funcs[i]() + "<br />");
}
在标注的部分,我们将内部函数赋值到result中。之后,在funcs中得到了函数的返回值result。实际上,funcs和result中全是对内部函数的指针。在使用funcs数组时,内部函数被调用(引用),然而createFunctions()早在创建funcs完毕后便结束调用,因此只留下自身本地活动对象给内部函数调用。此时的i为5,所以funcs得到的结果也全部是5。
因此,请务必区分在调用内部函数时,外部函数是否已经结束了调用。一般情况下,若内部函数是作赋值处理,在调用时外部函数一般已经结束调用,此时只能使用活动对象;若内部函数是作直接调用处理,则能够使用作用域链中的每一个变量。