Javascript学习——闭包

1.Javascript的闭包,说闭包离不了作用域,先看看作用域:

  先贴点基本代码:  

var n=110;

function funA(){   

 alert(n);
}

funA(); // 弹出结果:110 结果很正常,声明一个函数外部的变量,访问,弹出结果。

// 局部变量

function funB(){ 

   var nn=5;

}

alert(nn); // error 提示nn未定义;

再看下一个:

function funC(){   

 myNumber=998;
}

funC();
alert(myNumber);

这个会弹出什么结果?error?额,这个结果却是998了。。。与上一个的完全不同,这就是var关键字的作用了,如果在函数内部声明局部变量一定要带上var关键字,否则解释的时候在就被当做全局变量了,现在的myNumber就已经是全局变量了,所以可以访问到,而上个funB()中因为有关键字var的限制,参数是局部变量,函数外部无法访问到内部的局部变量,所以会出现错误。总的来说就是变量作用域照成的结果。

 

2.如果我想访问funB中的局部变量怎么办?

这时候可以这个样子,在funB方法中再做一些东西,如下:

function funB(){   

   var nn=5;  

  funD=function(){       

   alert(nn);  

  }

}

这样funD就可以访问到funB的局部变量nn了,对funD来说,funB父级内的都是可以访问的,而funB则无法访问funD中的内容,这就是Javascript的“链式作用域”结构(chain scope)所决定的。所以只要在funB中返回funD的结果,那么在funB函数外就可以调用funD()了。

function funB(){       

 var nn=5;      

 function funD(){       

    alert(nn);   

  }  

 return funD;

}
funB();// 弹出 结果5;

3.闭包:

  funD其实就是闭包(一个子函数),通过函数内部的子函数来访问局部变量,在函数内部和函数外部连接起来的一座桥梁,将变量的访问范围扩大但又不会破坏变量作用域安全的这一效果.

4.闭包的用途

   下面是闭包的一个例子:    

       function funMain(){

    var n=999;    

    nSet=function(value){

       n+=value;

    }    

    function fSon(){

      alert(n);

    }    

    return fSon;

  } 

  var result=funMain(); //对funMain的返回结果fSon的引用

  result(); // 第一次调用这就直接返回fSon 结果:999

  nSet(1000);// 注意nSet没有使用关键字var 

  result(); // 第二次调用结果:1999;

   这是demo中多了个nSet的匿名函数,而且这个nSet是funMain的子函数,所以nSet也是一个闭包,nSet没有关键字var,所以nSet可以直接在父函数外直接访问。第二次输出结果是1999,那么父函数中的局部变量n并没有在funMain第一次被调用完后就销毁,因为一直存在一个叫result的对funMain变量的引用,直到result被GC回收,然后funMain才会被回收。

5.注意事项:

  上个例子中的nSet可以在外部对函数的局部变量进行操作。那么这个就存在一定的危险了,它可以在外面修改父函数的局部变量,而且对父函数的变量一直引用消耗浏览器内存,对于内存的消耗是比较好处理的,只需要删除不必要的引用,标记delete就可以了。

对于在外部修改函数局部变量的问题,利用OO,把父函数当对象进行处理,这种闭包当做OO中的public属性,局部变量当做私有属性来处理会好一点,风险还是有的.

PS:木有胆量,那来产量!

posted @ 2012-12-07 20:27  Maculish  阅读(172)  评论(0编辑  收藏  举报