详解javascript闭包特性

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

闭包有三个特性:
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量

使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量。全局变量在每个模块都可调用,这势必将是灾难性的。

所以推荐使用私有的,封装的局部变量。

一般函数执行完毕后,局部活动对象就被销毁,,内存中仅仅保存全局作用域。但闭包的情况不同!

 

 1 function aaa() {  

 2       var a = 1;  

 3       return function(){

 4 alert(a++)

 5   };  

 6     }         

 7     var fun = aaa();  

 8     fun();// 1 执行后 a++,,然后a还在~  

 9     fun();// 2   

10     fun = null;//a被回收!!  

 

 

 

嵌套函数的闭包

 

 1 <script>

 2 function outer(){                         //外部函数

 3         var a = 5;

 4         function inner(){                         //内部函数

 5                 alert(a);

 6         }

 7         return inner;                             //返回内部函数,也可以写成return inner();

 8 }

 9 

10 var c = outer();                       

11 c();                                       //调用外部函数,开始执行

12 </script>

 

以上输出结果为5;
闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。
javascript的垃圾回收原理
(1)、在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收;
(2)、如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。


那么使用闭包有什么好处呢?使用闭包的好处是:
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在

一、全局变量的累加

1 <script>

2 var a = 1;

3 function abc(){

4         a++;

5         alert(a);

6 }

7 abc();              //2

8 abc();            //3

9 </script>

 

二、局部变量

 1 <script>

 2 

 3 function abc(){

 4         var a = 1;

 5         a++;

 6         alert(a);

 7 }

 8 abc();                       //2

 9 abc();                    //2

10 </script>

 

那么怎么才能做到变量a既是局部变量又可以累加呢?

三、局部变量的累加(闭包所能做到的)

 1 <script>

 2 function outer(){

 3         var x=10;

 4         return function(){             //函数嵌套函数

 5                 x++;

 6                 alert(x);

 7         }

 8 }

 9 var y = outer();              //外部函数赋给变量y;

10 y();                 //y函数调用一次,结果为11

11 y();                //y函数调用第二次,结果为12,实现了累加

12 </script>

js中的函数声明与函数表达式:
在js中我们可以通过关键字function来声明一个函数:

1 <script>

2 function abc(){

3         alert(123);

4 }

5 abc();

6 </script>

 

我们也可以通过一个"()"来将这个声明变成一个表达式:

1 <script>

2 (function (){

3         alert(123);

4 })();                   //然后通过()直接调用前面的表达式即可,因此函数可以不必写名字;

5 </script>

 

四、模块化代码,减少全局变量的污染

 

 1 <script>

 2 var abc = (function(){      //abc为外部匿名函数的返回值

 3         var a = 1;

 4         return function(){

 5                 a++;

 6                 alert(a);

 7         }

 8 })();

 9 abc();    //2 ;调用一次abc函数,其实是调用里面内部函数的返回值    

10 abc();    //3

11 </script>

 

五、私有成员的存在

 1 <script>

 2 var aaa = (function(){

 3         var a = 1;

 4         function bbb(){

 5                 a++;

 6                 alert(a);

 7         }

 8         function ccc(){

 9                 a++;

10                 alert(a);

11         }

12         return {

13                 b:bbb,             //json结构

14                 c:ccc

15         }

16 })();

17 aaa.b();     //2

18 aaa.c()      //3

19 </script>

 

七、在循环中直接找到对应元素的索引

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

 3 <head>

 4         <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />

 5         <title></title>

 6 <script>

 7 window.onload = function(){

 8         var aLi = document.getElementsByTagName('li');

 9         for (var i=0;i<aLi.length;i++){

10                 aLi[i].onclick = function(){        //当点击时for循环已经结束

11                 alert(i);

12                 };

13         }

14 }

15 </script>

16         

17 </head>

18 <body>

19         <ul>

20                 <li>123</li>

21                 <li>456</li>

22                 <li>789</li>

23                 <li>010</li>

24         </ul>

25 </body>

26 </html>

 

你可能感兴趣的:(JavaScript)