JavaScript专题(二)我眼中的闭包

我花了好长的时间,看了网上好多的博客才理解了(自以为)闭包的意义。
我分以下几点来讲闭包:

  • 俯(藐)视闭包----简单玩意儿(方法论),你可以选择看完就走

  • 变量的一生----变量的销毁和生存时间

  • 匿名函数----不是小透明的小透明

  • 闭包陷阱----万用的例子

  • 审视闭包----它的作用,整个JS的函数世界都是闭包?

  • 细看闭包----我不看这节!(欢迎跳过,但有闲情可以来看看,书画怡情)

  • 避免闭包----内存占用,或者不想用(任性)!,你真的用不到吗?有时候是这样的




1.俯视闭包:

假装写代码:

          过去,我在写代码,我是用二进制写的,我只知道0和1;
          如今,我在写代码,我用的是记事本,我知道abcd;
          未来,我在写代码,也许我根本不用学JS???一呼一吸就是法则?

闭包定义:

闭包是指有权访问另一个函数作用域中的变量的函数。

翻译:在今天,我可以不知道函数内部是怎么样运行的,它们已经被封装在了函数里,被语法所定义了,我只要知道toString()就是返回字符串就行了。这其实就是闭包。

我只要知道我能通过某种方式获取信息就行了。这种方式就是闭包。

function 科技发展(){           //现代版
  var 内部编译原理=xxx;
  return function 使用方法(莫须有的参数){
              通过xxx,你想做什么都可以;
 }
}
var 我要使用科技=科技发展();
我要使用科技(莫须有的参数);          
//就这样,我可以不懂(无法直接获取)xxx,但我懂使用(获取)方法就可以了

学过C++或者相似语言的还可发现,这跟类的私有变量很像对吧。我们可以用接口函数获取,但不能直接获取。

(1)闭包是一种设计原则,它通过分析上下文,来简化用户的调用,让用户在不知晓的情况下,达到他的目的;
(2)网上主流的对闭包剖析的文章实际上是和闭包原则反向而驰的,如果需要知道闭包细节才能用好的话,这个闭包是设计失败的;
(3)尽量少学习。 -------http://kb.cnblogs.com/page/110782/

其实,我们可以从两方面的角度看闭包。
----------a.从设计者的角度上,用户没法直接获得数据,其实也就是实现了数据的私有。
----------b.从使用者的角度上,用户可以通过另外的方式(这个方式也许更加简单、方 便,具体根据设计者来定)获得数据或者甚至操作封装好了的数据。

END.
想继续学请看下方。















2.变量的一生:
  • 在JS世界里面,有这样的清洁原则,环境中无法访问到的变量就被清除就像一个被所有人遗忘的人那样,所有人都觉得他死了。
  • JS里面有两种变量,一种是全局变量,一种是局部变量。局部变量是个依附着所属空间的东西,一旦所属空间没有,它也就灰飞烟灭了。而全局变量呢,它的生命周期就是js文件使用的周期。

所以如果你要销毁变量,如果是全局变量,那么你需要覆盖它,如果是局部变量你只要等待它所在的方法结束,它就自动销毁了。
function test(){var a=3;}

    alert(a);   //error,a 已经被销毁了
    for(var a=3;a<10;a++){}
    alert(a);  // 输出10,因为a在全局中定义,还没有被销毁
  • 但闭包是一种特殊的情况。闭包中的变量,这个函数的空间将会一直在内存中保留。
      function test(){
          var a=3;
          return function(){
              return a;
          }
      }
          b=test();
    

虽然在外部没法输出a,这是因为没法访问,但a还是存在于内存之中。因为内部的函数引用了外部的变量a(引用计数法垃圾清除,为0则删除),所以a还被人惦记着,自然也不会消亡。

3.匿名函数:
  • 什么是非匿名函数呢?
function I_have_name(){//do something}   
 //它就是有名字的函数,它的名字叫做   "I_have_name"
function (){//do something}              
 //它是匿名函数,它没有定义名字
  • 什么又是自执行函数呢?
(function (){
alert(3);
})();               //它就是自执行函数
(function auto(){
alert(3);
})();             //它也是自执行函数,效果同上
                    //也就是说那个auto没有卵用?(此句是版主自以为的)
//--------------------------------------------------
//此处还有一个坑,那就是如果
function(){
alert(3);
}();                //这样写是错的!!!!!!!!!!!!!!

为什么(function {// code})();可以被执行, 而function {// code}();却会报错?
答:
1.我们来看他们的区别,其实前者它叫函数声明,而后者它叫函数表达式。
2.JS的预编译的时候我先看函数声明,忽略函数表达式。就像给声明开了个后门一样。
3.当JS正式编译的时候,声明过的函数看到了(function{//code}就跳过了,因为它编译过了,所以,他只会看到()这个东西。???这个是什么玩意儿,于是函数就报错了。
4.而匿名函数还是完整的,所以能够正常执行。
5.还需要知道的是,自执行函数的标识可以是

!function(){}()              (function(){})()    
~function(){}()      void function(){}()

6.自执行函数是可以带参数的,格式是这样的!

function(num){
alert(num);
}(3);                  输出3
4.闭包陷阱

然后我们来说一个常见的闭包例子,这是一个闭包的副作用。

var arr=[1,2,3];
  var obj={};
  var test=function(){
      for(var i=0;i<arr.length;i++)
      {
          obj[i]=function(){
              alert(i);
          }
      }
  }

  test();
  for(var i=0;i<arr.length;i++)
  {
      obj[i]();             //最后的输出是输出了三个3.
  }

按照正常的思维,最后应该是obj[0]=0,obj[1]=1,obj[2]=2,但是真正的过程是这样的:

  • 在obj[i]的函数域里面,因为要输出i,而它自己的空间里,是没有i的,于是它就往外层找,在外层找到了i,而外层的这个i呢,它是被保存在外围的函数里面的。
  • 接下来是关键,外层的这个函数是一个对象对吧(所有的函数都是一个对象),而我们访问的正是这个对象的i,而在这个对象中保存的i其实是变量的地址,最终它是以10保存的。
  • 所以,我们的解决办法就是,跟obj[i]里面的i一样,创造一个两个函数之间沟通的机会,实现即时按值传递

var test=function(){
      for(var i=0;i<arr.length;i++)
      {
          obj[i]=function(canshu){
              alert(canshu);
          }(i);
      }
}
test();
  for(var i=0;i<arr.length;i++)
  {
      obj[i]();             //最后分别输出:0,1,2   达成预期
  }

如果你看懂了上面的,你就明白了。
对!我使用了匿名函数!一个带参数的匿名函数。这里的(i),是在外围的区域里面的,跟obj[i]中i一模一样,而作为内部函数里,它是被赋值(或者我们还可以说是复制)给canshu,所以,它是即时按值传递的!!!
(PS:自己发明的词语,仅供参考,主要的问题在于,我不知道底层到底是如何运行的,说它是引用又觉得不太对劲)

这个过程的实现也成功避免了闭包带来的陷阱。

5. 审视闭包:

其实我们甚至可以说,在全局环境中写的function,都是一个闭包。


参考文献
1.超级推荐的文章
2.什么是闭包,闭包的优缺点
3.Javascript闭包——懂不懂由你,反正我是懂了
4.浅析匿名函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容