JavaScript 闭包

这很6!!!

 

计数器困境

设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。

你可以使用全局变量,函数设置计数器递增:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8">
 5 <title>菜鸟教程(runoob.com)</title>
 6 </head>
 7 <body>
 8 
 9 <p>全局变量计数。</p>
10 <button type="button" onclick="myFunction()">计数!</button>
11 <p id="demo">0</p>
12 <script>
13 var counter = 0;
14 function add() {
15     return counter += 1;
16 }
17 function myFunction(){
18     document.getElementById("demo").innerHTML = add();
19 }
20 </script>
21 
22 </body>
23 </html>

每次递增1!

计数器数值在执行 add() 函数时发生变化。

但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。

如果我在函数内声明计数器,如果没有调用函数将无法修改计数器的值:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8">
 5 <title>菜鸟教程(runoob.com)</title>
 6 </head>
 7 <body>
 8 
 9 <p>局部变量计数。</p>
10 <button type="button" onclick="myFunction()">计数!</button>
11 <p id="demo">0</p>
12 <script>
13 function add() {
14     var counter = 0;
15     return counter += 1;
16 }
17 function myFunction(){
18     document.getElementById("demo").innerHTML = add();
19 }
20 </script>
21 
22 </body>
23 </html>

每次都是1!

 

以上代码将无法正确输出,每次我调用 add() 函数,计数器都会设置为 1。

JavaScript 内嵌函数可以解决该问题。


JavaScript 内嵌函数

所有函数都能访问全局变量。  

实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。

JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8">
 5 <title>菜鸟教程(runoob.com)</title>
 6 </head>
 7 <body>
 8 
 9 <p>局部变量计数。</p>
10 <p id="demo">0</p>
11 <script>
12 document.getElementById("demo").innerHTML = add();
13 function add() {
14     var counter = 0;
15     function plus() {counter += 1;}
16     plus();    
17     return counter; 
18 }
19 </script>
20 
21 </body>
22 </html>

结果是1!

如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。

我们同样需要确保 counter = 0 只执行一次。

我们需要闭包。


JavaScript 闭包

还记得函数自我调用吗?该函数会做什么?

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8">
 5 <title>菜鸟教程(runoob.com)</title>
 6 </head>
 7 <body>
 8 
 9 <p>局部变量计数。</p>
10 <button type="button" onclick="myFunction()">计数!</button>
11 <p id="demo">0</p>
12 <script>
13 var add = (function () {
14     var counter = 0;
15     return function () {return counter += 1;}
16 })();
17 function myFunction(){
18     document.getElementById("demo").innerHTML = add();
19 }
20 </script>
21 
22 </body>
23 </html>

结果每次递增1!!

解析:

变量 add 指定了函数自我调用的返回字值。

自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。

add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。

这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。

计数器受匿名函数的作用域保护,只能通过 add 方法修改。

Note 闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。

这写法很 6!

posted @ 2015-04-07 13:51  oldmonk  阅读(159)  评论(0编辑  收藏  举报
Fork me on GitHub