• 闭包


      要了解闭包就需要了解javascript的变量作用域(scope)和作用域链(scope chain)。

      变量的作用域就是:全局变量拥有全局作用域,它在javascript代码中任何地方都是有定义的;局部变量拥有局部作用域,它只在局部作用域(一般是全局函数或者函数的嵌套函数)中有定义/*函数中的this,和arguments也是局部变量,全局作用域中也有this这个变量,但无arguments变量*/。

      先来个变量作用域的例子:  

    //例1
    var scope="global";//定义一个全局变量
    function f1(){//声明式定义一个函数f1
        alert(scope);   //global
    }
    f1();//执行函数f1
    //例2
    var scope="global";
    function f1(){
      var scope="local";
      alert(scope);//local    
    }
    f1();
    //例3
    var scope="global";
    function f1(){
      alert(scope);//undefined
      var scope="local";   
    }
    f1();

    解释:例1中全局变量scope在任何地方都有定义,所以在f1中可以访问;例2中f1中局部变量scope将全局变量屏蔽了;例3中,局部变量scope在f1中有定义(),所以在f1中任何地方都可以访问,注意是定义,不包括赋值(这种情况也叫声明提前)。

      作用域链:它的用途就是保证变量和函数的有序访问。

      从例子入手:

    var n1=11;
    function f1(){
      var n2=12;
    alert(n1);
    } } f1();

    解释:当定义f1函数时会发生几件事情:1.创建一个与之关联的变量对象,被保存在内部的[[Scope]]属性,javascript代码无法访问;2.创建一个作用域链,这个作用域链预先包含window对象。当调用f1时:会将f1关联的变量对象推至作用域链的前端,此时这条作用域链保存着两个变量对象(其实保存的是指向变量对象的指针列表,也就是内存地址),每个变量对象都保存着他们作用域的变量。当需要alert(n1)时,变量n1会先根据作用域链来搜索,从顶端开始,一直到末端(window对象),直到找到为止,如果没找到,就会抛出错误。

         闭包(closure):有权访问另外一个函数作用域中变量的函数。根据作用域和作用域链我们可以得知,函数内部可以访问函数外部的变量,而函数外部无法访问函数内部的变量,但是有些时候,我们需要在函数外部访问函数内部的变量,这就是闭包要干得事情!

      创建闭包最常见的方式是在函数内部创建一个函数。如下:

    var n1=10;
    function f1(){
        var n2=11;
        alert(n1);
        function f2(){//f2闭包
             alert(n2);
        }
    return f2; } ff1
    =f1();//执行f1,并将返回结果即f2函数赋给ff1 ff1(); //执行ff1,即执行f2函数 。

    解释:通过f2函数对变量进行某些操作,再在函数外部调用f2,看起来就像是在函数外部对f2进行操作一样。

      闭包的用途:闭包不仅能够访问其他函数内部的值,也可以使他们内部的值一直保存在内存中。

    var n1=10;
    function f1(){
        var n2=11;//私有变量
        alert(n1);
        function f2(){//f2闭包
             alert(n2++);
        }
      return f2; } ff1
    =f1();//执行f1,并将返回结果即f2函数赋给ff1,10 ff1(); //执行ff1,即执行f2函数,11 ff1();//12

    解释:按照常理,当f1()调用完了之后,f1中的变量n2应该被销毁才对,但是实际上n2一直保存在内存中!我的理解是f2函数被赋值给全局变量ff1,而全局变量ff1不会被销毁,所以f2函数也存在,它的作用域链也存在,而此作用域链保存着n2,所以n2未被销毁。

      闭包与this:全局作用域的this指向的是window,匿名函数作用域具有全局性,一般情况下函数中this也指向window。例子如下:

    var name="window";
    obj={
       name:"local",
       thisname:function(){
              return function(){//返回一个匿名函数
                     alert(this.name);
               }
       }
    };
    obj.thisname()();//window
    //obj.thisname()表示function(){alert(this.name);}这个函数
    //obj.thisname()()表示function(){alert(this.name)}这个函数的执行结果

    解释:this指向的是一个匿名函数关联的对象,但是匿名函数具有全局性,其this指向window对象。

      闭包与单例模式:单例模式的定义是使一个类产生唯一的实例。实现思路是先判断是否有具有一个实例,如果有就返回,没有就创建一个再返回。看一个例子:

    var createmask=function(){
          var mask;
          return function(){
                return mask||(mask=document.body.appendChild(document.createElement("div")));   
          }  
    
    }()//匿名函数立即执行,同时避免变量污染命名空间
             
  • 相关阅读:
    yablog: calculate cosine with python numpy
    HDF
    numarray 1.5.1
    Angles between two ndimensional vectors in Python Stack Overflow
    3D stem plot
    linq to sql一定要注意的地方!
    将IRepository接口进行抽象,使它成为数据基类的一个对象,这样每个子类都可以有自己的最基础的CURD了
    (SQL)比较一个集合是否在另一个集合里存在的方法
    linq to sql统一更新方法,直接返回更新的对象(解决更新后再刷新数据错误显示问题)
    LINQ TO SQL数据实体应该这样设计(解决多表关联问题)
  • 原文地址:https://www.cnblogs.com/wang-jiang/p/3836694.html
Copyright © 2020-2023  润新知