首先我们来看一个常见的例子:
var fnArr = [];
for(var i=0; i<10; i++){
fnArr[i] = function(){
return i;
};
}
console.log(fnArr[3]()); //10
解析:不知道各位是否能理解这里为什么输出是10,但我还是解释一下,怕一些小伙伴还在疑惑之中。
实际上,这里的fnArr[i]每次获得的是一个函数,即
fnArr[0]=function(){return i}
fnArr[1]=function(){return i}
fnArr[2]=function(){return i}
.....
fnArr[9]=function(){return i}
而for循环结束以后,在全局中i=10
所以调用fnArr[3]()即return i=10;
所以fnArr[0]到fnArr[9]输出才都是10
当然,我们可以每次都立即执行循环中的函数,使之达到我们想要的效果:
var fnArr = [];
for(var i=0; i<10; i++){
fnArr[i] = function(){
return i;
}();
}
console.log(fnArr[3]); //3
console.log(fnArr[1]); //1
console.log(fnArr[10]); //undefined
console.log(fnArr[9]); //9
下面我们就利用闭包来让它实现fnArr[i]输出对应的i值:
var fnArr = [];
for(var i=0; i<10; i++){
fnArr[i] = (function(num){
return function f1(){
return num;
}
})(i);
}
console.log(fnArr[3]()); //3
这里实际上就是利用闭包,使每次的i值都始终保存在内存中,而实际上这里的fnArr[i]就是闭包f1,只不过每个f1读取父级函数的num变量值不同而已。但通过闭包使 i =0~9的值都分别保存在了每次循环的父级函数中,所以调用fnArr[3]会输出3,因为此时f1父函数中的num值为3。
另外一种闭包的方法:
var fnArr=[];
for(var i=0;i<10;i++){
(function(){
var num = i;
fnArr[i] = function f1(){
return num;
}
})()
}
console.log(fnArr[3]); //[Function: f1]
console.log(fnArr[3]()); //3
原理和前一种一样,利用闭包读取父函数内部的变量,并且让这些变量的值始终保持在内存中。
下面我们再使用闭包实现一个自增函数,每次调用使内部变量加1:
function f1(){
var i=0;
return f2 = function(){
return i++;
}
}
var add=f1();
console.log(add); //[Function: f2],add就相当于函数f2
console.log(add()); //0
console.log(add()); //1
console.log(add()); //2