天天看點

js閉包了解

1,js的鍊式作用域

[html] 

​​view plain​​

​​copy​​

​​

​​

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script type="text/javascript">
  5. //js鍊式作用域:父對象的所有變量,對子對象都是可見的,反之則不成立。
  6. function f1(){
  7. n=1;
  8. function f2(){
  9. var n2=11;
  10. alert("f2:n="+n);
  11. }
  12. f2();//1
  13. alert("n2:"+n2);//提示n2 is not defined。
  14. }
  15. f1();
  16. </script>
  17. </head>
  18. <body></body>
  19. </html>

2,閉包

上方代碼中的f2函數就是閉包。

可以了解為:閉包就是可以通路其他函數内部變量的函數,例如f2通路f1,也了解為局部變量函數,因為f2就是f1的子函數。

3,閉包的用途

閉包的用處很多,最大通常有兩個:一個是讀取函數内部變量(f2讀取f1),另一個是讓這些變量的值始終保持在記憶體中。

第一種用途可以從上方代碼中看到,看第二種用途:

[html] 

​​view plain​​

​​copy​​

​​

​​

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script type="text/javascript">
  5. function f1(){
  6. var n=1;
  7. nAdd=function(){
  8. n+=1;
  9. }
  10. //f2把n儲存在記憶體中
  11. function f2(){
  12. alert("f2:n="+n);
  13. }
  14. return f2;
  15. }
  16. var result=f1();
  17. result(); //n=1,記憶體中有n=1
  18. nAdd();//記憶體中n+1
  19. result(); //n=2
  20. </script>
  21. </head>
  22. <body></body>
  23. </html>

這個代碼中可以看到,f2運作了兩次,從第二次運作結果可以看到,n并沒有在第一次運作之後被清楚。

原因在于:f1是f2的父函數,而f2被賦給了一個全局變量(result),這導緻f2始終在記憶體中,而f2的存在依賴于f1,是以f1也始終在記憶體中,不會在調用結束後,被垃圾回收機制(garbage collection)回收。注意代碼中的匿名函數nAdd,這個也是閉包,且相當于一個set函數,函數外部調用可以給局部變量指派。

4,使用閉包注意

1)由于閉包會使得函數中的變量都被儲存在記憶體中,記憶體消耗很大,是以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導緻記憶體洩露。解決方法是,在退出函數之前,将不使用的局部變量全部删除。

2)閉包會在父函數外部,改變父函數内部變量的值。是以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把内部變量當作它的私有屬性(private value),這時一定要小心,不要随便改變父函數内部變量的值。

5,終極代碼

(1)

[html] 

​​view plain​​

​​copy​​

​​

​​

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script type="text/javascript">
  5. var name = "The Window";
  6. var object = {
  7. name : "My Object",
  8. getNameFunc : function(){
  9. return function(){
  10. return this.name;
  11. };
  12. }
  13. };
  14. alert(object.getNameFunc()());  //The Window
  15. </script>
  16. </head>
  17. <body></body>
  18. </html>

解決這個問題,首先清楚this指的是什麼。可以在getNameFunc中alert一下,發現是window,就是全局環境,因為是全局變量,是以輸出“The Window”,問題是為什麼this指的是全局環境,參考:​​js中的this​​ .

(2)

[javascript] 

​​view plain​​

​​copy​​

​​

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script type="text/javascript">
  5. function outerFun(){
  6. var a=0;
  7. function innerFun(){
  8. a++;
  9. alert(a);
  10. }
  11. return innerFun;  //注意這裡
  12. }
  13. var obj=outerFun();
  14. obj();  //結果為1
  15. obj();  //結果為2
  16. var obj2=outerFun();
  17. obj2();  //結果為1
  18. obj2();  //結果為2
  19. </script>
  20. </head>
  21. <body></body>
  22. </html>

繼續閱讀