一篇文章带你了解JavaScript 函数闭包

开发 前端
本文基于JavaScript基础。从函数的基本概念,(变量和全局 )。函数为什么需要闭包,使用闭包可以让私有变量成为可能。通过案例(计数器)的讲解, 以及对嵌套函数中闭包的应用能够更好的理解。

[[400839]]

大家好,我是前端进阶者。

JavaScript变量属于 本地 或者 全局 范围,使用闭包可以让私有变量成为可能。

一、全局变量

一个函数可以访问所有定义在函数 内部 的变量。

  1. function myFunction() { 
  2.     var a = 4; 
  3.     return a * a; 

但是函数也可以访问定义在函数 之外 的变量。

  1. var a = 4; //全局变量 
  2. function myFunction() { 
  3.    return a * a;  

第一个例子中,a是一个局部变量.。局部变量只能在定义的函数内使用。

全局变量可以被页面(和窗口)中所有脚本使用(和更改),具有相同名称的全局变量和局部变量是不同的变量。修改一个,不修改其他。

没有关键字var创建的变量,总是全局的,即使是在函数中创建的。

二、变量的生命周期

全局变量只要应用程序(窗口/网页)存在,它就存在。

局部变量生命周期较短。它们在函数被调用时被创建,当函数完成时被删除。

三、为什么需要闭包?

假设要使用一个变量来计数某物,并且希望该计数器可用于所有函数。可以使用一个全局变量和一个增加计数器的函数。这个时候就需要闭包。

案例:一个计数器

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4. <meta charset="UTF-8"
  5. <title>项目</title> 
  6. </head> 
  7. <body style="background-color: aqua;"
  8. <p>使用全局变量计数</p> 
  9.  
  10. <button type="button" onclick="myFunction()">计数!</button> 
  11.  
  12. <p id="demo">0</p> 
  13.  
  14. <script> 
  15. var counter = 0; 
  16.  
  17. function add() { 
  18. return counter += 1; 
  19.  
  20. function myFunction() { 
  21. document.getElementById("demo").innerHTML = add(); 
  22.   /* the counter is now equal to 3*/ 
  23.     }  
  24. </script> 
  25. </body> 
  26. </html> 

注:

计数器只被add()函数改变。问题是,页上的任何脚本可以改变计数器,无需调用add(),如果在函数中声明计数器,没有调用的时候,没有人能改变它 add()。

  1. function add() { 
  2.    var counter = 0; //局部变量 
  3.    counter += 1; 
  4.  
  5. add(); 
  6. add(); 
  7. add(); 
  8.  
  9. // the counter should now be 3, but it does not work ! 

每次都要调用add()函数,计数器被设置为1。

四、JavaScript嵌套函数

所有函数都可以访问全局作用域。

事实上,在JavaScript中,所有函数都能访问它们外部的变量。JavaScript支持嵌套函数. 嵌套函数可以访问它们 上面(外部) 的作用域。

实例中, 内部函数 plus() 在父函数中可以访问 counter 变量。

  1. function add() { 
  2.    var counter = 0; 
  3.    function plus() {counter += 1;} 
  4.    plus();     
  5.    return counter; 

完整代码:

  1. <!DOCTYPE html> 
  2. <html> 
  3. <title>项目</title> 
  4.  
  5. <body style="background-color: aqua;"
  6.  
  7. <h2> JavaScript嵌套函数</h2> 
  8.  
  9. <p id="output"></p> 
  10.  
  11. <script> 
  12. function outer() { 
  13. var counter = 0; 
  14.  
  15. function inner() { 
  16. counter++; 
  17. inner(); 
  18. return counter; 
  19.  
  20. document.getElementById("output").innerHTML = `计数器是: ${outer()}`; 
  21. </script> 
  22.  
  23. </body> 
  24. </html> 

如果能从外部调用plus()函数,这可能已经解决了计数器的困境,还需要找到一种方法来执行 counter = 0 只执行一次,需要闭包。

五、JavaScript 闭包

自调用函数

变量add被分配了自调用函数的返回值,自调用函数只运行一次. 它将counter设置为零(0),并返回函数表达式。

  1. var add = (function () { 
  2.    var counter = 0; 
  3.    return function () {return counter += 1;} 
  4. })(); 
  5.  
  6. add(); 
  7. add(); 
  8. add(); 
  9.  
  10. // the counter is now 3 

这样 add 变成了一个函数. "精彩的" 部分是它可以在父作用域中访问counter。

注:

这就是所谓的 JavaScript 闭包, 它使函数有“私有”变量成为可能。counter受匿名函数的作用域保护, 并且只能使用add函数修改。

六、总结

本文基于JavaScript基础。从函数的基本概念,(变量和全局 )。函数为什么需要闭包,使用闭包可以让私有变量成为可能。通过案例(计数器)的讲解, 以及对嵌套函数中闭包的应用能够更好的理解。

丰富的效果图的展示,能够帮助更好的去理解闭包这一概念。

希望能够帮助你更好的学习JavaScript 。

 

责任编辑:姜华 来源: 前端进阶学习交流
相关推荐

2021-01-29 18:41:16

JavaScript函数语法

2023-06-15 10:11:08

JavaScript函数表达式

2021-06-04 09:56:01

JavaScript 前端switch

2020-11-10 10:48:10

JavaScript属性对象

2021-02-02 18:39:05

JavaScript

2023-09-06 14:57:46

JavaScript编程语言

2021-05-18 08:30:42

JavaScript 前端JavaScript时

2023-07-30 15:18:54

JavaScript属性

2021-01-26 23:46:32

JavaScript数据结构前端

2021-03-05 18:04:15

JavaScript循环代码

2021-03-09 14:04:01

JavaScriptCookie数据

2024-01-30 13:47:45

2021-06-24 09:05:08

JavaScript日期前端

2023-06-06 15:45:40

JavaScript数组

2021-05-07 14:17:01

JavaScript元素网页

2021-11-26 11:10:07

JavaScript 节点导航

2021-04-20 11:20:24

Java开发运算符

2023-07-25 16:06:57

JavaScript对象

2023-07-14 14:56:47

JavaScriptwindow

2023-08-27 15:18:17

JavaScriptRegExp
点赞
收藏

51CTO技术栈公众号