JavaScript闭包

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内。这种特性称为“闭包”。

函数定义时的作用域链到函数执行时依然有效。

var uniqueInteger=(function(){
                     var counter=0;
                     return function(){return counter++;};//返回另外一个函数
}());

这段代码定义了一个立即调用的函数(函数的开始带有左圆括号),因此是这个函数的返回值赋值给uniqueInter。当外部函数返回之后,其他任何代码都无法访问counter变量,只有内部的函数才能访问到它。像counter一样的私有变量,在同一个外部函数内定义的多个嵌套函数都可以访问它。

function counter(){
  var n=0;
  return {
      count:function(){return n++},
      reset:function(){n=0;}
    };
}
var c=counter(),d=counter();//创建两个计数器
c.count()                   //=>0
d.count()                   //=>0
c.reset()                   
c.count()                   //=>0
d.count()                   //=>1

两个方法count()和reset()都可以访问私有变量n。每次调用counter()都会创建一个新的作用域链和一个新的私有变量。

function counter(n){//函数参数n是一个私有变量
  return {
     get count(){return n++;},
     set count(m){
     if(m>=n) n=m;
     else throw Error("count can only be set to a larger value");
     }
   };
}

var c=counter(1000);
c.count            //=>1000
c.count            //=>1001
c.count=2000  
c.count            //=>2000
c.count=2000       //Error!

使用参数n来保存私有状态,属性存取器方法可以访问n。调用counter的函数就可以指定私有变量的初始值了。

使用闭包技术来共享私有状态的通用做法:

function addPrivateProperty(o,name,predicate){
  var value;//属性值是保存在局部变量中,而没有存储在对象o中
  o["get"+name]=function(){return value;};
  o["set"+name]=function(v){
    if(predicate && !predicate(v))
      throw Error("set"+name+":invalide value "+v);
    else 
      value=v;
  };
}

var o={};
addPrivateProperty(o,"Name",function(x){return typeof x=="string";});
o.setName("A");
concole.log(o.getName());
o.setName(0);//错误类型

在同一个作用域链中定义两个闭包,这两个闭包共享同样的私有变量和变量,是一项非常重要的技术。但是要小心不希望共享的变量共享给了其他闭包。正确做法是:

function constfunc(v){return function(){return v;};}

var funcs=[];
for(var i=0;i<10;i++) funcs[i]=constfunc(i);

func[5]() //=>5
还需注意的是,this是JavaScript的关键字,而不是变量。 闭包在外部函数里是无法访问this的,除非外部函数将this转存为一个变量,以便嵌套的函数能够访问它。

你可能感兴趣的:(javaScript)