闭包

  要了解闭包就需要了解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")));   
      }  

}()//匿名函数立即执行,同时避免变量污染命名空间
         

posted on 2014-07-12 22:04  复读机  阅读(170)  评论(0编辑  收藏  举报

导航