首页 > 代码库 > JS基础——闭包
JS基础——闭包
有关JS中闭包的理解和使用。
一、简介
子函数可以使用父函数中的局部变量,这种行为就叫做闭包。通常指,有权访问另一个函数作用域中的变量的函数。创建时,通常在一个函数中创建另一个函数,通过另一个函数访问这个函数的局部变量。
function box() { var user = 'Lee'; return function () { //通过匿名函数返回 box()局部变量 return user; }; } alert(box()());这里通过一个匿名函数来访问父函数中的user变量,并且返回这个变量的值,那么在外部我们可以通过直接调用来box()来访问匿名函数。
在这里看似没什么作用,有点儿画蛇添足。那么为什么还要使用闭包呢?
当然,它也有自己的优点:通过闭包实现变量永驻内存,避免全局变量实现累加
二、利用闭包实现累加
传统方式:声明一个全局变量实现累加
var age=100; //全局变量的声明 function box(){ age++; } box(); alert(age);通过这种方式,如果在大型软件开发中,全局变量会造成很多不可想象的麻烦,通常我们应该尽量减少全局变量的使用。但是,这里如果使用局部变量的声明方式,又不能实现累加。
局部变量方式:
function box(){ var age=100; age++; return age; } alert(box()); //需要多次调用box方法来进行,每次执行都会对age进行重新初始化始终为101那么如何避免局部变量每次的初始化,这里就用闭包来解决。
利用闭包,变量永驻内存,实现累加:
function box(){ var age=100; //box中的局部变量 return function(){ //匿名函数 age++; return age; } } var b=box(); alert(b()); //这里调用多次box函数后可实现累加,内存中保留有age变量的值 alert(b());通过上面这种闭包的形式可以实现累加,但是需要调用多次函数,我们可以利用循环来改善这一现象。
三、循环中的闭包
闭包在循环中的应用可利用下面这些方法来达到同样的效果
1、匿名函数返回一个数组
function box(){ var arr=[]; for (var i=0;i<5;i++){ arr[i]=function(){ return i; } } return arr; //返回一个数组 } for (i=0;i<5;i++) //连续实现循环输出 { alert(box()[i]()); //结果为5个5 }注意:通过box()返回一个数组,那么如果在下面输出循环中若执行alert(box()[i])时,那么会执行循环中的函数即,打印出5个匿名函数function(){return i} ,所以,这里我们要注意加上()来执行循环中的匿名函数,才能真正输出数字。那么为什么为5个5呢?
原因:在每次输出循环时,我们都会执行box()函数,而每次执行时,其实,box函数已经执行完毕,即其实,每次执行输出循环中的一次,box中for循环就执行了5次,即执行到i++=5,而每次循环arr[i]=5,因此每次输出循环结果都为5.其实,这里输出循环中每次输出的都是box函数for循环了5次以后的结果5,而box内部每次循环时,因匿名函数未自我执行,结果均为匿名函数的函数体。只有到第五次,结果才为5。
问题出现在哪里呢?如果在每次循环结束时,匿名函数可以自我执行,那么每次循环完成后,就会返回arr,数组中就会有5个元素分别为0,1,2,3,4,那么在接下来的循环输出时,就可以将这5个元素依次输出了。具体解决方案详见2.直接传参自我执行。
2、直接传参自我执行
function box(){ var arr=[]; for(var i=0;i<5;i++){ arr[i]=(function (num){ return num; })(i); //通过直接传参自我执行实现循环挨个输出 } return arr; //自我执行后,每次循环都会返回arr } var b=box(); for(var i=0;i<5;i++){ alert(b[i]);//这里直接b[i]即可,不用再执行内部的匿名函数了 }这里利用的是通过匿名函数自我传参的方式,实现循环,其实整体上和第一种方式是一样的,只是一个参数执行的区别。
三、循环中返回匿名函数
function box(){ var arr=[]; for(var i=0;i<5;i++){ arr[i]=(function (num){ //num在这里 return function(){ //返回一个闭包 return num; } })(i); //把i传给num } return arr; } var b=box(); for( var i=0;i<5;i++){ alert(b[i]()); }
第三种通过返回一个闭包,这种方式如果利用JS进行逐句调试会发现,它的执行顺序和结果与第一种是一样的。即先执行box()返回5个function,可是最后执行完输出循环后,结果显示为0,1,2,3,4这里就是运用了闭包可以使变量永驻内存的原理,在执行box()循环时,它将变量i保存了起来,而在输出时,直接按顺序输出即可。
小结:通过闭包来实现变量存储在内存中,在很多应用中确实很方便,但是由于它占据了内存,所以在一些用到大量变量的程序中,会影响到程序执行的性能,所以闭包还是要慎用!
JS基础——闭包