热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分分钟搞懂JS-闭包函数

1抛开概念!直接上代码,看实例23vari100;4functionadd1(){5alert(i);6i++;7}8fun
 1 //抛开概念!直接上代码,看实例
 2 
 3 var i=100;
 4 function add1(){
 5    alert(i); 
 6    i++;
 7 }
 8 function add2(){
 9    var j=100;
10    alert(j); 
11    j++; 
12 }
13 
14 //测试;
15 
16 //    add1(); //100
17 //    add1(); //101
18 //    add1(); //102
19 //    
20 //    add2(); //100
21 //    add2(); //100
22 //    add2(); //100
23 
24 /*为什么呢 原因很简单
25 i 是全局变量,只有页面关闭的时候,才会被GC回收;
26 j 是局部变量,函数执行完毕后就 被GC 回收;
27 
28 问:有没有办法将j 变成"全局变量"呢?
29 A同学答:有,将j写在外面(尼玛,傻逼啊)
30 B同学答,用return(有点接近了) 然后用全句变量来接收;
31 C同学答:闭包(完美)    
32 */
33 function add3(){
34   var j=100;
35   function fun(){
36    alert(j);
37    j++;
38   }
39    return fun; //注意这里;
40 }
41 
42 /*
43 测试:
44 
45 var obj=add3(); //执行add3()函数,同时返回了fun的引用(也就是fun的函数体)
46 
47 //直接alert(obj) 你会看到他的函数体- function fun(){....} 再加上一个括号(),就可以执行了
48 
49    obj(); //100
50 
51    obj(); //101
52 
53    obj();//102
54 
55  */

 

当函数a的内部函数b 被函数a 外的一个变量引用的时候,就创建了一个闭包。

简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。

那么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收

最后,如果你能看懂这段代码你就理解了闭包!

 1    var name="window";
 2    var object={
 3      name:"my object",
 4      getName:function (){
 5          return function (){
 6              return this.name; 
 7          }
 8      }
 9       
10   }
11  alert(object.getName()()); //window

闭包的多种写法:

写法一:

  function f1(){
     var index=1;
     function f2(){
        alert(index);
        index++; 
     }
     return f2;
  }
  //调用
  var test=f1();
  test(); //1
  test(); //2
  test(); //3

写法二:

  function outer(){
      var index=1;
     return function(){ //使用匿名函数
         alert(index);
         index++;
     }
  }
 var bibao=outer();
  bibao();
  bibao();
  bibao();

写法三: 

var outer=(function (){
      var index=1;
      return function (){
         alert(index);
         index++;  
      }
    
})();

outer();
outer();
outer();

写法四:

var outer=null;
(function (){
    var index=1;
    function inner(){
      alert(index++);    
    };
    outer=inner;
})();
outer();
outer();
outer();

总之就是函数之间的嵌套,变量之间的互相引用;

Javascript的垃圾回收原理

(1)、在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收; 
(2)、如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

 总结:

 

 

实例:

html代码:

          <ul>
                    <li>123li>
                    <li>456li>
                    <li>789li>
                    <li>010li>
            ul>

 js代码:(错误方式) 

window.Onload= function(){
            var lis = document.getElementsByTagName('li');
            var len=lis.length;
            for (var i=0;i){
                    lis[i].onclick = function(){        //当点击时for循环已经结束
                    alert(i);
                    };
            }
    }

js代码:(错误方式)

window.Onload=function (){
     var index=0;
     var lis=document.getElementsByTagName("li");
     var len=lis.length;
     for(var i=0;i){
         lis[i].onclick=function (){
            alert(index);  //这样做,避免了i直接等于3,但是,却没有绑定到指定的对象上滴呀
            index++;
            if(index==len){
                index=0;
            }
         }
     }
}

js代码:(改进方式一)面向对象+this关键字的使用

window.Onload=function (){
  var lis=document.getElementsByTagName("li");
  var len=lis.length;
  for(var i=0;i){
      lis[i].index=i; //给每个变量动态的绑定一个属性,并赋值
      lis[i].Onclick=function (){
          var temp=this.index; //然后使用this关键字;
          alert(temp);  
      }
  }
}

js代码改进二:让i独立出来,index作为他的一个“副本”! i的变化不再影响到我们index

function showInfo(obj,index){
   obj.onclick=function (){
     alert(index);   
   }
}

window.onload=function (){
  var lis=document.getElementsByTagName("li");
  var len=lis.length;
  for(var i=0;i){
     showInfo(lis[i],i);//i的改变和 index无关滴呀  
  }
}

原理解析一:

   var index=1;
   
   function change1(){
     index=index+1;
   }
   
   function change2(){
    index=index+2;
   }
   change1();
   change2();
   alert(index); //4

原理解析二:

   function change1(val){
     var temp=val;
     temp=temp+1;
   }
   
   function change2(val){
     var temp=val;
     temp=temp+2;
   }
   
   change1(index);
   change2(index);
   alert(index);
   //这样这不会改变;

最总版本:(关键-传递副本)

 var index=1;
  (function (val){
     val=100;  
  })(index);
   
  (function (val){
     val=10000;  
  })(index);
   
   alert(index);

js代码:(闭包实现)模块化代码,减少全局变量的污染-最好的方式;

我们需要在每次循环时为变量 i 值创建一个拷贝,重点在:模块话代码,形成一个独立的区域;

window.Onload=function (){
     var lis=document.getElementsByTagName("li");
     var len=lis.length;
     for(var i=0;i){
         (function (e){
              lis[e].onclick=function (){
                 alert(e);  
              }
         })(i); //形成一个独立的区域互补干扰
     }
}

继续扩展,这段代码是不是闭包?还是仅仅是一个你们匿名函数的自执行呢? 

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

 

 //闭包概念:闭包是指某种程序语言中的代码块允许一级函数存在并且
  //在一级函数中所定义的自由变量不能被释放,直到一级函数释放前,
  //一级函数外也能应用这些未释放的自由变量;
 var shit=function (y){
    var x=y;
    return function (){
      alert(x++); //这里调用了一级函数的局部变量x
      //上下连个交换着尝试
      alert(y--); //这里调用参数变量,是自变量;    
    }}(5);
    
shit();  // 5 5
shit();  // 6 4
shit();  // 7 3

 

关于内存泄露的问题;

function closure(){
   var div=document.getElementById("div1");//div用完之后一直驻留在内存中
   div.Onclick=function (){
      alert(div.innerHTML);  //这里导致了内存泄露得呀
      //长期扎住在内存中得,没有得到是释放;   
   }
}

//优化:
function closure2(){
  var div=document.getElementById("div1");
  var text=div.innerHTML;
   div.onclick=function (){
      alert(text);  //这里导致了内存泄露得呀
      //长期扎住在内存中得,没有得到是释放;   
   }
   div=null;
}

再推荐一篇关于闭包的好文章

http://segmentfault.com/a/1190000000652891

应用

看我另外一篇文章:

js 动画实现原理,就是闭包的一个典型应用的呀;

 

 

 

 

 

 


推荐阅读
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文总结了Java中日期格式化的常用方法,并给出了示例代码。通过使用SimpleDateFormat类和jstl fmt标签库,可以实现日期的格式化和显示。在页面中添加相应的标签库引用后,可以使用不同的日期格式化样式来显示当前年份和月份。该文提供了详细的代码示例和说明。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
author-avatar
king1994
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有