• js闭包理解实例小结


    Js闭包

    闭包前要了解的知识 

     1. 函数作用域

    (1).Js语言特殊之处在于函数内部可以直接读取全局变量

     

    <script type="text/javascript">
    var n=100;
    function parent(){
      alert(n);
    }
    parent();//100
    </script>

     

    如果在php

     

    <?php
    $n=100;
    function parent(){
      echo $n;
    }
    parent();//会报错 n未定义
    ?>

     

    (2).在函数外部无法读取函数内的局部变量

    <script type="text/javascript">
    function parent(){
      var m=50;
    }
    parent();
    alert(m);//报错 m未定义
    </script>

    注意函数内部声明变量时一定要加var,否则就声明了一个全局变量

     

    function parent(){
     m=50;
    }
    parent();
    alert(m);//50

     

    //当然在php里更是如此了,
    <?php
    function parent(){
      global $m;//全局 ,定义与赋值要分开
      $m=50;
    }
    parent();
    echo $m;//50
    ?>
    //没global的话,一样会报没定义的错误

    有时,需要得到函数内部的的局部变量,就需要变通的方法实现

    利用js变量作用域的特点,如在函数内部定义子函数,对于子函数来说,父函数就是它的全局,子函数可以访问父函数里的变量(对于整个js代码来说又是局部变量)

     

    <script type="text/javascript">
    function parent(){
       var m=50;
       function son(){
            alert(m);
       }
       return son;
    }
    var s=parent();//将结果保存在全局里
    s();//50
    </script>

    Parent内部所有局部变量对其子函数来说都是可见的,但其子函数内的局部变量对其父函数是不可见的,这就是js特有的链式作用域结构,子对象会一级一级地向上查找所有父对象的变量,父对象的所有变量对子对象都是可见的,反之不成立!

     上面的son函数就是闭包

    有些同学可能这样

    function parent(){
       var m=50;
       function son(){
            alert(m);
       }
     }
    parent();
    son()//会报 函数son未定义

    注意 在javascript里,在函数里声明的函数都是局部的,函数运行完后就释放了

    注意这点与php的区别

     

    <?php
    function parent(){
      function son(){
          $m=50;
          echo $m;
      }
    }
    parent();
    son();//输出50 不会报错
    ?>

     

    闭包

    函数内部定义函数,连接函数内部和外部的桥梁

    闭包的作用有2:

    一是前面提到的读取函数内部的变量,

    二是让这些变量的值保存在内存中,实现数据共享

    下面是几个闭包的例子

    <script type="text/javascript">
    var cnt=(function(){
        var i=0;
        return function(){
            alert(i);
            i++;
        }
    })();
    cnt();//0
    cnt();//1
    cnt();//2
    cnt();//3
    
    </script>

    把匿名函数的执行结果(即对里面子函数的声明赋给全局变量cut),i就保存在内存里了

    执行cut()时就直接从内存取值了,i只有cnt()函数才能调用,直接alert(i)是不行的

    还可以向闭包内传参

    var cnt=(function(num){
    return function(){
        alert(num);
        num++;
      }
    })(5);
    cnt();//5
    cnt();//6
    cnt();//7
    //当然还可以调用时传参
    var cnt=(function(){
        var i=0;
    return function(num){
        num+=i;
        alert(num);
        i++;
      }
    })();
    cnt(1);//1
    cnt(2);//3
    cnt(3);//5

    为了对闭包有更好的理解,我们看以下代码

    比如我想返回一个数组,数组里面有5个函数,第一个函数弹出0,第二个弹出1...

      代码如果这样写

    function box(){
      var arr=[];
      for(i=0;i<5;i++){
          arr[i]=function(){return i;}
        }
     return arr;   
    }
    var a=box();
    alert(a);//包含五个函数体的数组
    alert(a[0]());
    alert(a[1]());

    弹出的函数体

    function(){return i;}

        

    }

    最后这个i4,之后++成为5

    For循环停止

    发现均弹出5,明显不符合我们的要求

    解决方案1

    自我即时执行里面的函数

    function box(){
      var arr=[];
      for(i=0;i<5;i++){
          arr[i]=(function(num){return i;})(i);
        }
     return arr;   
    }
    var a=box();
    for(var i=0;i<a.length;i++){
      alert(a[i]);
    }

    但是我们发现 返回的数组里的元素是函数执行的结果,但我们想要的是函数

    有得升级我们的代码

    解决方案闭包实现

     

    function box(){
    var arr=[];
            for(var i=0;i<5;i++){
    
                     arr[i]=(function(num){
                         return function(){return num;}
                     })(i);
    
             }
    return arr;         
    }
    
    var arr=box();
    
    for(var i=0;i<5;i++){
    
        alert(arr[i]());//0,1,2,3,4
    }

     

    关键代码

    arr[i]=(function(num){

      return function(){return num;}

     })(i);

    i=0 时 

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

    1

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

     

     

     

     这就是闭包的好处!

  • 相关阅读:
    TextView-setCompondDrawables用法
    android 相对布局RelativeLayout中的一些属性的使用和实例
    登录时旋转等待效果
    使用slidingmeu_actionbarsherlock_lib的问题和The hierarchy of the type MainActivity is inconsistent
    ActionBarSherlock SlidingMenu整合,解决SlidingMenu example的getSupportActionBar()方法不能用问题
    String,StringBuffer和StringBuilder的区别
    File.separator使用
    Android常用异步任务执行方法
    adb server is out of date. killing...
    adb shell root
  • 原文地址:https://www.cnblogs.com/HKUI/p/3329805.html
Copyright © 2020-2023  润新知