现在的位置: 首页 > 综合 > 正文

js闭包理解

2018年01月24日 ⁄ 综合 ⁄ 共 2951字 ⁄ 字号 评论关闭

1,js的链式作用域

[html] view
plain
copy在CODE上查看代码片派生到我的代码片

  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在CODE上查看代码片派生到我的代码片

  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在CODE上查看代码片派生到我的代码片

  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在CODE上查看代码片派生到我的代码片

  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>  

抱歉!评论已关闭.