• 闭包和立即执行函数


    闭包就是能够读取其他函数内部变量的函数。

    function a(){
        var n = 0;
        function inc() {
            n++;
            console.log(n);
        }
        inc();  
        inc(); 
    }
    a(); //控制台输出1,再输出2

    function a(){

        var n = 0;

        this.inc = function () {

            n++;

            console.log(n);

        };

    }

    var c = new a();

    c.inc();    //控制台输出1

    c.inc();    //控制台输出2

    function a(){
        var n = 0;
        function inc(){
           n++; 
           console.log(n);
        }
        return inc;
    }
    var c = a();
    c();    //控制台输出1
    c();    //控制台输出2
    var c1 = a();
    c1();    //控制台输出1
    c1();    //控制台输出2

    闭包陷阱:

    function createFunctions(){
        var result = new Array();
        for (var i=0; i < 10; i++){
            result[i] = function(){
                return i;
            };
        }
        return result;
    }
    var funcs = createFunctions();
    for (var i=0; i < funcs.length; i++){
        console.log(funcs[i]());
    }

    乍一看,以为输出 0~9 ,万万没想到输出10个10? 

    解决闭包问题:

    function createFunctions() {

        var result = new Array();

        for (var i = 0; i < 10; i++) {

            (function(i) {//添加一个立即执行的函数

                result[i] = function() {

                    return i;

                };

            })(i);

        }

        return result;

    }

    var funcs = createFunctions();

    for (var i = 0; i < funcs.length; i++) {

        console.log(funcs[i]());

    }

    var result = new Array(), i;
    result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    ...
    result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    i = 10;
    funcs = result;
    result = null;
     
    console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
    console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
    ...
    console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10

     function f1(){

        n=999;

        function f2(){

          return (n); // 999

        };

    return f2;

    };

    f1()();

    //控制台输出999

    立即执行函数:

     (function f1(){

        n=999;

        function f2(){

          return (n); // 999

        };return f2;

      })();

    //控制台输出

    function f2(){

       return (n); // 999

     }

     (function f1(){

        n=999;

        function f2(){

          return (n); // 999

        };return f2;

      })()();

    //控制台输出

    999

     (function f1(){

        n=999;

        function f2(){

          return (n); // 999

        };return f2;

      }())();

    //控制台输出

    999

    function f1(){

        var n=999;

        nAdd=function(){n+=1}

        function f2(){

          alert(n);

        }

        return f2;

      }

      var result=f1();

      result(); // 999

      nAdd();

      result(); // 1000

    在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

    为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

    这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

    使用闭包的注意点

      1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除

      2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

     

    内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。

    var name = "The Window";  

    var object = {    

        name: "My Object",

            getNameFunc: function() {      

            return function() {        

                return this.name;     

            };    

        }

    };

    alert(object.getNameFunc()()); //The Window

    //控制台输出The Window

    function outerFun() {

        var a = 0;

        console.log(a);

    }

    var a = 4;

    outerFun();

    console.log(a);

    //控制台输出0,4

    作用域链

    function outerFun() {

        //没有var

        a = 0;

        alert(a);

    }

    var a = 4;

    outerFun();

    alert(a);

    结果为 0, 0 真是奇怪, 为什么呢 ?

        作用域链是描述一种路径的术语, 沿着该路径可以确定变量的值。 当执行a = 0时, 因为没有使用var关键字, 因此赋值操作会沿着作用域链到var a = 4;

    并改变其值。

  • 相关阅读:
    什么是布局?Android中的布局是怎样的?
    如何优化UI布局?
    Android SDK提供的常用控件Widget “常用控件”“Android原生”
    Android中Adapter类的使用 “Adapter”
    Android自定义属性
    Android中View的绘制流程(专题讲解)
    Android的自定义View及View的绘制流程
    如何创建新控件? “复合控件”“定制控件”
    Android应用程序支持不同屏幕(尺寸、密度)
    支持不同Android设备,包括:不同尺寸屏幕、不同屏幕密度、不同系统设置
  • 原文地址:https://www.cnblogs.com/songjn/p/9469803.html
Copyright © 2020-2023  润新知