首页 > 其他 > 详细

小白也来说闭包

时间:2015-12-20 14:38:48      阅读:127      评论:0      收藏:0      [点我收藏+]

  作为向我一样的前端小白来说,闭包是一个比较难懂的地方。但是它在js中确实相当的重要,对于提高写js的水平也有很大帮助。前几天通过园子里的文章和群里大神的讲解,对闭包有了一定的了解。于是在这里做一下复习,有什么不对的地方,希望各位指正。

  闭包的概念

  由于官方给出的概念实在有些难懂,就不写了。简单的来说,在函数内再定义一个函数,就产生了一个闭包。

  闭包的作用

  为什么要在函数里再定义一个函数呢?有什么作用呢?这个就要牵扯的js的作用域链问题了。  

1 window.a=111;
2 
3 function test(){
4     alert(a);            
5 }
6         
7 test();//111

 

  在window下定义一个a=111和函数test(),这里产生了2个作用域,一个事根作用域,也就是window对应的作用域,另一个是函数test的作用域,其中test的作用域是window作用域的子节点。当在test里alert(a)时,现在test自身的作用域内查找a,由于a没有定义,于是向上一级作用域查找,知道根作用域(这里直接是根作用域),未找到是返回undefined。也就是说,在子作用域里可以访问祖先作用域里的变量。那么如果先要在祖先作用域里访问子作用域的变量应该怎么办?这个就是闭包的作用了,允许我们在祖先作用域里访问子作用域的变量。

 1 function test(){
 2     var a=1;               
 3 }
 4         
 5 console.log(a);//undefined  
 6 
 7 //在正常情况下直接在全局里alert(a)是不行的
 8 //为了访问这个a,我们可以在test函数里再定义并且返回一个函数,
 9 
10 function test(){
11     var a=1;
12 
13     return function(){
14          console.log(a);
15     }            
16 }
17         
18 var a=test();
19 a();//1

 

  在第10行的test函数里,我们返回了一个匿名函数用于打印a,当我们在window作用域下调用时,能打印出a,因为这个匿名函数也产生了一个作用域,并且挂在了test作用域之下,所以我们能够访问到a。

我们再拿一个在讲解闭包时用的比较多的例子来看一下。

 1 var result=[];
 2 
 3 function test(){
 4   for(var i=0;i<3;i++){
 5     result[i]=function(){console.log(i)};
 6   }
 7 }
 8 
 9 test();
10 result[0]()//3
11 result[1]()//3
12 result[2]()//3

  在这里result[0],result[1],result[2]执行时打印的都是3,为什么会这样,我们来画个图解释一下

技术分享

  在执行完test()之后会有这样一个情况,作用域链上有3个对象,分别是window的作用域,test的作用域和匿名函数的作用域。而数组result的3个元素都指向匿名函数。当执行result[0]()时,匿名函数开始在自身作用域查找i,因为没有定义,于是向上级test作用域查找,在test作用域里,i经过for循环,已经变成了3,所有result[0],result[1],result[2]都等于3。那么我们想得到0,1,2应该怎么办呢?我们可以在test里面再定义一个函数,如代码:

 1 var result=[];
 2         
 3 function test(){   
 4             
 5   for(var i=0;i<3;i++){
 6       result[i]=(function(num){ return function(){console.log(num)} })(i);
 7   }
 8 }    
 9         
10 test();
11 result[0]();//0
12 result[1]();//1
13 result[2]();//2

 

  这里又发生了什么事呢?首先执行完test()之后,result[0],result[1],result[2]都指向匿名函数function(){console.log(num)}。当他们执行的时候,依旧是查找num,在上一级匿名函数中找到了参数num,这个num是多少呢?是在上级函数test()执行时赋值的i,因此,这里的num分别为0,1,2。于是就有了最后我们希望得到的结果。在解释里,我们好像并没有提到闭包。这正是我希望的,因为我们需要的是掌握这样一个原理,而不是一个概念。闭包那个生涩的概念反而会阻碍我们更好的理解。

  好了,这篇就到这里了。希望各位看官能看懂…  本人的表达能力确实不太好…

小白也来说闭包

原文:http://www.cnblogs.com/nicoBlog/p/5060711.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!