zoukankan      html  css  js  c++  java
  • 匿名函数和闭包

    匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂。

    // //普通函数
    // function box(){
    //     return 'lee';
    // };
    
    
    // //匿名函数
    // function(){                        //执行的时候会显示错误
    //     return 'lee';
    // };
    
    //把匿名函数自我执行的返回值赋值给变量
    var b=function(){                        //单独的匿名函数,是无法执行的 就算执行也无法调用
        return 'lee';
    };
    
    alert(b);                    //这样会打印出匿名函数的结构
    alert(b());                    //这样会打印出匿名函数的返回值
    // 匿名函数自我执行
    (function (){                        //(匿名函数)(); 第一圆括号放匿名函数,第二个圆括号执行
        return 'lee';            //()表示执行
    })();
    
    
    alert((function (){
        return 'lee';
    })());
    //自我执行匿名函数的传参
    
    
    
    alert((function(age,name){
        return age+name;
    })(100,200)
    );
    //函数里的匿名函数
    function box(){
        return function(){           //闭包
            return 'lee';
    }
    };
    
    alert(box()());     //box()  返回是匿名函数的结构    box()()返回函数中匿名函数的返回值

    闭包:

      闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

    //通过闭包可以返回局部变量
    function box(){
        return function(){                    //通过匿名函数返回box()局部变量
            return 'Lee';
        };
    };
    
    alert(box()());                    //通过box()()来直接调用匿名函数返回值
    var b=box();            
    alert(b());                        //另一种调用匿名函数返回值

    使用闭包有一个优点,也是他的缺点;就是可以把局部变量留在内存中,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以拓建使用私有的,封装的局部变量)

    //全局变量累加
    // var b=100;
    // function box(){
    //         b++;
    // };
    
    // alert(b);
    // box();
    // alert(b);
    
    //使用匿名函数实现局部变量驻留内存中从而累加
    function box(){
        var age=100;
        return function(){
            age++;
            return age;
        };
    };
    
    var b=box();
    alert(b());                        //每次都要匿名函数
    alert(b());
    alert(b());
    alert(b());
    //循环里的匿名函数的取值问题1
    function box(){
        var arr=[];
        for(var i=0;i<5;i++){
            arr[i]=function(){
                return i;
            };    
        };
        return arr;
    };
    
    
    var b=box();
    for(var i=0;i<5;i++){
        alert(b[i]());        //这么写取值返回的都是5
    }
    
    
    //循环的匿名函数取值问题2
    
    function box(){
        var arr=[];
        for(var i=0;i<5;i++){
            arr[i]=(function(num){            //通过自我及时执行匿名函数
                return num;
            })(i);    
        };
        return arr;
    };
    
    
    var b=box();
    for(var i=0;i<5;i++){
        alert(b[i]);        //这么写取值返回的都是5
    }
    
    //循环里的闭包的取值问题3
    function box(){
        var arr=[];
        for (var i =0; i<5;i++) {
            arr[i]=(function(num){            //arr【0】=0,arr[1]=1,arr[2]=2.......
                return function(){            //闭包可以将变量驻留到内存中。
                    return num
                };
            })(i);
        }
    
    
        return arr;
    };
    
    
    var b=box();
    for(i=0;i<5;i++){
        alert(b[i]());
    };

     内存泄漏

      由于IE的JScript和DOM对象使用不同的垃圾收集方式,因此闭包在IE中会导致一些问题,就是内存泄漏的问题,也就是无法销毁驻留在内存中的元素,以下代码有连个知识点还没有学习到,以个是DOM,一个是事件

    function divShow(){
        var b=document.getElementById("di");      //b  用完之后会一直驻留到内存中
        b.onclick=function(){
            alert(b.innerHTML);      //这里用b导致内存泄漏
        };
    }
    
    divShow();

    模仿块级作用域

      javascript没有块级作用的概念

    //块级作用域(私有作用域)
    
    function box(count){
        for(var i=0;i<count;i++)    //i不会因为离开了for块就失效
            var i;                    //就算重新声明,也不会前面的数据
            alert(i);               
    };
    
    box(2);

      以上两个例子,说明javascript没有块级语句的作用域,if(){}  for(){} 等没有作用域,如果有,出了这个范围:就应该被销毁了,就算重新声明同一个变量也不会改变他的值。

      javascript不会提醒你是否多次声明了同一个变量:遇到这种情况,它只会对后续I的声明视而不见(如果初始化了,当然还会被执行)使用模仿块级作用域可避免这个问题。

    //模仿块级作用域(私有作用域)
    
    function box(count){
        (function(){      //包含自我执行函数,就可以实现私有作用域
            for(var i=0;i<count;i++)   
            alert(i); 
    })();
        alert(i);    //报错,无法访问  被销毁了
        };
        
    box(2);       

       使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁,这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数,一般来说,我们都应该尽可能少像全局作用域中添加变量和函数,在大型项目中,多人开发的时候,过多的全局变量和函数很容易导致命名冲突,引起灾难性的后果,如果采用块级作用域(私有作用域)每个开发者既可以使用自己的变量,又不必担心搞乱全局作用域。

     私有变量

      javascript没有私有属性的概念,所有的对象属性都是共有的,不过,却有一个私有变量的概念,任何在函数中定义的变量,都可以认为是私有变量,因为不能再函数的外部访问这些变量

    function box(){
        var b=100;            //私有变量,外部无法访问
    };

    而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量,而利用这一点,都可以创建用于访问私有变量的公有方法

    //对象共有化
    function Box(){
    this.age=100; //属性,共有的 this.run=function(){ //方法,共有的 return '运行中....'; } }; var box=new Box(); alert(box.age); //返回100 alert(box.run()); //返回运行中 //私有化 function Box(){ var age=100; //私有属性 function run(){ //私有方法 return '运行中'; }; this.publicGo=function (){ //对外可见的公共接口,特权方法 return age+run(); }; }; var box=new Box(); alert(box.age); //返回 undefined 找不到 alert(box.run()); //返回 undefined 找不到 alert(box.publicGo()); //返回 100 运行中
    //通过构造函数传参
    function Box(value){
        var age=value;
        this.getAge=function(){
            return age;
        };
    };
    
    var box=new Box('杜伟');
    alert(box.getAge());

    什么叫单例:就是永远只实例化一次,其实就是字面量对象声明方式(无法第二次实例化就叫单例)。

    模块模式

    var box={                //这样写其实已经实例化了
        age:100,
        run:function(){            
            return '运行中';
        }
    };
    
    alert(box.age);    //直接就可以调用
    alert(box.run());
    //字面量私有化
    
    var box=function(){
        var age=100;                //私有变量
        function run(){                //私有函数
            return '运行中....';
        };
        return {                    //返回对象
            publicGo:function (){    //对外公共接口的特权方法
                return age+run();
            }
        };
    }();
    
    alert(box.publicGo());

    字面量的对象声明,其实在设计模式中可以看作是一种单例模式,所谓单例模式,就是永远保持对象的一个实例

     

     

     

  • 相关阅读:
    MHA-Failover(GTID,Auto_Position=0)
    PXC中的GTIDs
    MySQL备份与恢复
    MySQL复制框架
    pt-table-checksum检测不出主从差异处理
    MHA-Failover可能遇到的坑
    MHA-手动Failover流程(传统复制&GTID复制)
    MSSQL-SELECT&UPDATE动作要申请的锁
    sybench压测下模拟误truncate数据恢复
    gtid_executed和gtid_purged变量是如何初始化的
  • 原文地址:https://www.cnblogs.com/xiaowie/p/10277483.html
Copyright © 2011-2022 走看看