注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

百鬼夜行

身是菩提树,心如明镜台,时时勤拂拭,勿使惹尘埃。

 
 
 

日志

 
 

我再来说说闭包,保证初学者能看懂(转自老姚的博客)  

2015-12-14 16:27:57|  分类: js原理及提醒记忆 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
之前讲闭包的文章,很多初学者,还是没懂,还是在写一篇。原文地址:http://www.w3cfuns.com/blog-5471724-5409375.html
先说句题外话,你看完之后,觉得讲得清楚的话,点个赞,只要两个就能上今日推荐,让更多人看到。如果认为我讲的不好,甚至讲错了,欢迎指正。
本文开始,先看最简单的代码。
  1. function a(){
  2.         var x = 0;
  3.         function b(){
  4.                 x++;
  5.                 return x;
  6.         }
  7.         console.dir(b); 
  8. }
  9. a();
复制代码


从上面可以看出,b函数中是保存a作用域中的x的,虽然从chrome中可以看出,x保存在b的closure中,
但是我们也不会吧b叫做闭包的。因为此时b不能在a的作用域之外调用从而访问a中的变量x;

我们先看看在a中调用b的情形
  1. function a(){
  2.         var x = 0;
  3.         function b(){
  4.                 x++;
  5.                 return x;
  6.         }
  7.         b();
  8.         b();
  9.         console.dir(b); 
  10. }
  11. a();
复制代码


b中的确实保存了x的最新值。再一次声明,b不能叫做闭包,在我看来就是作用域链的问题。就像你说女人是人,是正确的。如果你把女人当人的定义来说。我就不同意了。
作用域链能解释明白的事情,就没必要发明闭包这个概念。

作用域链是产生闭包这个现象的核心条件之一,还差另一个重要的因素,才是我们说的闭包现象。那就是你这个b函数必须在a的作用域之外调用才行。
怎么能在a的作用域之外调用b呢,两个办法。1.把b做为a的返回值结构的一部分。2.把b绑定dom的事件上。
对于第一种,a能返回b,运行完a之后,保存a的返回结果,自然拿到b函数,然后再调用b,这样确实是在a的作用域之外调用b了。
至于第二种,把b绑定dom的click事件上,我们点击dom触发b运行,也可以说在a的作用域之外,调用了b。
多说一句,js中为啥有闭包现象,函数能当参数传,能当返回值,这才是核心原因,也是js这么屌的原因。

这里主要来说说第一种情况
  1. function a(){
  2.         var x = 0;
  3.         function b(){
  4.                 x++;
  5.                 return x;
  6.         }
  7.         return b;         
  8. }
  9. var c =a();
  10. c();
  11. c();
  12. console.dir(c);
复制代码


从打印来看c正是a中的b,c运行两次,相当在a中运行了b两次。

而初学者,之所以容易弄不明白,总觉得运行两次c,认为里面的x仍始终是1;
原因很简单,c()这么调用不是运行a,实际是运行b,而a呢,你始终运行了一次。如代码中var c = a()这句话。
初学者之所以觉得x始终是1,其实像如下代码调用,才是你错误理解的方式
  1. function a(){
  2.         var x = 0;
  3.         function b(){
  4.                 x++;
  5.                 return x;
  6.         }
  7.         return b;         
  8. }
  9. var c =a();
  10. c();
  11. var d =a();
  12. d();
  13. console.dir(c);
  14. console.dir(d);
复制代码


c和d其实都是b,注意这里两个b不是同一个b,是长的一模一样的双胞胎,因为a运行了两次,因而是两个。建议你研究研究,值类型和引用类型的区别。
至于绑定dom,自己敲敲代码吧。
本文完。
  评论这张
 
阅读(32)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017