闭包与匿名函数

关于闭包,对于js的初学者来讲,对于闭包关于变量作用域的部分存在着很大的困惑。为了搞清楚这个问题,我们先应该先了解匿名函数,这对于理解闭包的问题有很大的帮助

var box=function(){

//函数体

}

如上面的代码所示,创建一个函数并将函数赋值给一个变量box,这种情况下创建的函数叫做匿名函数,以为function关键字后面没有标识符即没有函数名,匿名函数的name属性是空字符串(匿名函数有时候也叫拉姆达函数)。

匿名函数的执行方法如下:

方法1

var box=function(){};

box()

方法2(匿名函数的自我执行)

(function(){})()

(function(number){})(number)     //这里给匿名函数传参

闭包我们可以把它简单的理解为定义在函数里面的匿名函数,如例1

1

Function sayHello(){

return function(){        //匿名函数

alert(“hello world!”);

};

}

在例1这个sayHello函数里,我们将一个匿名函数作为sayHello这个函数的返回值。我们要执行sayHello这个函数里面的匿名函数的方法有:

方法1sayHello()()

方法2

var b=sayHello();

b();

对于方法2,我们要清楚的知道将sayHello函数执行后赋值给一个变量b,其实就是把sayHello函数执行后的返回值赋值给变量b,所以在这里我们可以将这个过程简化为:var b=function(){ alert(hello world!);};,然后在执行(这对于后面理解有的问题有很大帮助)

现在我们来看两个关于闭包的问题:

问题1代码如下:

function box(){

var num=0;

return function(){

alert(++num);

}

}

box()();  //弹出1

var sum1=box();

sum1();     //弹出1

sum1();    //弹出2

var sum2=box(); 

Sum2()    //弹出1

对于这里,对于弹出结果,我们不理解的应该是执行完第二个sum1()”后会弹出2,这是因为使用匿名函数会将变量驻留在内存中,内存中保留函数执行后的结果,所以会弹出2。按照我的理解这有点像这里间接把定义在box函数中的变量num暂时变成了一个全局变量。但在重新执行box()时,原先驻留在内存中的num值就没有了,因此执行“sum2()”弹出的是1。也可以想成在执行“var sum=box()”时,给number重新进行了赋值。

注:这里的闭包在执行是可能会产生内存驻留,在IE浏览器中,由于浏览器自身的回收机制,会产生内存泄漏,造成严重的后果,因此,要避免使用闭包

问题2

function box(){

var arr=[];

for(var i=0;i<10;i++){

arr[i]=function(){return i;};

}

}

相信很多人和我一样刚开始认为arr[]里是[0,1,2,3,4,5,6,7,8,9],可是当想要弹出arr[i]里面的i时,发现都是10,这和我们的设想不同。现在我们来分析为什么会产生这样的结果

首先,我们先想一下之前写的将一个匿名函数赋值给一个变量,然后在看这个问题就很简单了,当程序每循环一次的时候,是将一个匿名函数赋值给arr[i],匿名函数并没有执行,arr[i]里面并没有保存i,而是保存了一个个匿名函数,当退出循环时,i的值为10,如果我们要执行arr[i]里面的匿名函数,弹出的i的值肯定为10,和我们的预期结果是不一样的。如果想要弹出我们预期一样的结果,可以运用匿名函数的自我执行,通过匿名函数传递参数的方法将i赋值给arr[i],如下面的代码:

function box(){

var arr=[];

for(var i=0;i<10;i++){

arr[i]=(function(num){return num;})(i);

}

}

理解了这个,我们就很容易理解下面的代码:

var btn=[];

function act(){

for(var i=0;i<5;i++){

btn[i].onclick=function(){alert(i);};

}

}

这段代码几乎和问题2一样,只是加了点击事件,但是其实原理不多。当我们点击按钮的时候,弹出的都是5。因为每循环一次,我们都只是将一个匿名函数赋值给but[i]绑定的onclick事件,这个过程在我们点击按钮的时候都已经完成了,这时如果i没有别的操作,i的值为5,当我们点击按钮的时候,弹出的都是5。我们可以将代码改为:

 for (var i=0;i<5;i++){

   btn[i].onclick=function(arg){

      return function(){alert(arg);};

}(i);

}

阅读更多
个人分类: js
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

闭包与匿名函数

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭