感谢大神~!不是原博...数组
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = i; } return arr; } alert(box()) //正常状况不须要闭包,就能够达到预期效果,输出结果为一个数组0,1,2,3,4
有时咱们须要在for循环里面添加一个匿名函数来实现更多功能,看下面代码闭包
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = function(){ return i; //因为这个闭包的关系,他是循环完毕以后才返回,最终结果是4++是5 } //这个匿名函数里面根本没有i这个变量,因此匿名函数会从父级函数中去找i, } //当找到这个i的时候,for循环已经循环完毕了,因此最终会返回5 return arr; } //alert(box()); //执行5次匿名函数自己 //alert(box()[1]); //执行第2个匿名函数自己 //alert(box().length); //最终返回的是一个数组,数组的长度为5 alert(box()[0]()); //数组中的第一个数返回的是5,这是为何?
上面这段代码就造成了一个闭包:函数
闭包是指有权访问另外一个函数做用域中的变量的函数,建立闭包的常见的方式,就是在一个函数内部建立另外一个函数,经过另外一个函数访问这个函数的局部变量。post
在for循环里面的匿名函数执行 return i 语句的时候,因为匿名函数里面没有i这个变量,因此这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,因此这个box获得的是一个数组[5,5,5,5,5]。spa
解决方案1code
在看解决方案一以前,咱们先看一下匿名函数的自我执行:blog
匿名函数自我执行的写法是,在函数体外面加一对圆括号,造成一个表达式,在圆括号后面再加一个圆括号,里面可传入参数。ip
例以下代码:作用域
(function(){ alert('lee'); //匿名函数自我执行(匿名函数)() })();
咱们再来看解决方案1:it
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = (function(num){ //自我执行,并传参(将匿名函数造成一个表达式)(传递一个参数) return num; //这里的num写什么均可以 })(i); //这时候这个括号里面的i和上面arr[i]的值是同样的都是取自for循环里面的i } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[0]);
经过给匿名函数传参,而传递的这个参数i是每次执行for循环里面的i,每次传递的参数i的值都不同,匿名函数里面的num接收传递的参数i,因此box()最终输出结果为[0,1,2,3,4]
解决方案2
这种方案的原理就是在匿名函数1里面再写入一个匿名函数2,这个匿名函数2须要的num值会在他的父级函数匿名函数1里面去寻找,而匿名函数1里面的num值就是传入的这个参数i,和上面例子中的i是同样的,
function box(){
var arr = [];
for(var i=0;i<5;i++){
arr[i] = (function(num){
//num在这里 //原理和上面一种方法同样的,因此能够实现闭包
return function(){ //在这个闭包里面再写一个匿名函数
return num;
};
})(i)
}
return arr;
}
//alert(box());
//alert(box()[1]);
//alert(box().length);
var b = box();
alert(b[0]());
box()最终返回结果[0,1,2,3,4],
解决方案3
若是将一个匿名函数自我执行的时候赋值给一个变量,那么这个匿名函数中的圆括号的能够去掉的,看下面代码,
var tip = function(){ //这样把匿名函数自我执行的时候赋值给一个变量,那么圆括号是能够去掉的 alert('lee'); }();
利用匿名函数的这一特色,咱们能够将解决方案1中的代码改进一下:
var arr = []; for(var i=0;i<5;i++){ arr[i] = function(num){ return num; }(i); } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[4]);