JavaScript中闭包的概念、原理、作用及应用

开发 前端
闭包:有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数。

 一、闭包概念

闭包:有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数。

[[314779]]

从官方定义我们知道闭包是一个函数,只不过这个函数有[超能力],可以访问到另一个函数的作用域。

为什么说这个叫做[超能力]呢?

因为我们知道函数作用域是独立的、封闭的,外部的执行环境是访问不了的,但是闭包具有这个能力和权限。

那闭包是怎样的一个表现形式呢?

第一,闭包是一个函数,而且存在于另一个函数当中

第二,闭包可以访问到父级函数的变量,且该变量不会销毁

  1. function person(){ 
  2.     var name = '有鱼'
  3.     function cat(){ 
  4.         console.log(name); 
  5.     } 
  6.     return cat; 
  7. var per = person();// per的值就是return后的结果,即cat函数 
  8. per();// 有鱼 per()就相当于cat() 
  9. per();// 有鱼 同上,而且变量name没有销毁,一直存在内存中,供函数cat调用 
  10. per();// 有鱼 

 

二、闭包原理

闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。

例如:

 

  1. var age = 18; 
  2. function cat(){ 
  3.     age++; 
  4.     console.log(age);// cat函数内输出age,该作用域没有,则向外层寻找,结果找到了,输出[19]; 
  5. cat();//19 

 

看到这里,大家都会说这不就是最简单的函数和变量形式吗?闭包在哪里?别急,我们接着往下看:

如果我们再次调用时,结果会一直增加,也就变量age的值一直递增。

 

  1. cat();//20 
  2. cat();//21 
  3. cat();//22 

 

如果程序还有其他函数,也需要用到age的值,则会受到影响,而且全局变量还容易被人修改,比较不安全,这就是全局变量容易污染的原因,所以我们必须解决变量污染问题,那就是把变量封装到函数内,让它成为局部变量。

 

  1. function person(){ 
  2.     var age = 18; 
  3.     function cat(){ 
  4.         age++; 
  5.         console.log(age); 
  6.     } 
  7.     return cat; 
  8. person();// 19 
  9. person();// 19 

 

这里又出现问题了,每次调用函数person,进入该作用域,变量age就会重新赋值为18,所以cat的值一直是19;所以需要做一下调整:

 

  1. var per = person();//per相当于函数cat 
  2. per();// 19 即cat() 这样每次调用不在经过age的初始值,这样就可以一直增加了 
  3. per();// 20 
  4. per();// 21 

 

而且变量age在函数内部,不易修改和外泄,相对来说比较安全。

三、闭包作用

作用1:隐藏变量,避免全局污染

作用2:可以读取函数内部的变量

同时闭包使用不当,优点就变成了缺点:

缺点1:导致变量不会被垃圾回收机制回收,造成内存消耗

缺点2:不恰当的使用闭包可能会造成内存泄漏的问题

这里简单说一下,为什么使用闭包时变量不会被垃圾回收机制收销毁呢,这里需要了解一下JS垃圾回收机制;

JS规定在一个函数作用域内,程序执行完以后变量就会被销毁,这样可节省内存;使用闭包时,按照作用域链的特点,闭包(函数)外面的变量不会被销毁,因为函数会一直被调用,所以一直存在,如果闭包使用过多会造成内存销毁。

 

四、闭包应用

需求:实现变量a 自增

1、通过全局变量,可以实现,但会污染其他程序

 

  1. var a = 10; 
  2. function Add(){ 
  3.     a++; 
  4.     console.log(a); 
  5. Add(); 
  6. Add(); 
  7. Add(); 

 

2、定义一个局部变量,不污染全局,但是实现不了递增

 

  1. var a = 10; 
  2. function Add2(){ 
  3.     var a = 10; 
  4.     a++; 
  5.     console.log(a); 
  6. Add2(); 
  7. Add2(); 
  8. Add2(); 
  9. console.log(a); 

 

3、通过闭包,可以是函数内部局部变量递增,不会影响全部变量,完美!!

 

  1. var a  = 10; 
  2. function Add3(){ 
  3.     var a = 10; 
  4.     return function(){ 
  5.         a++; 
  6.         return a; 
  7.     }; 
  8. }; 
  9. var cc =  Add3(); 
  10. console.log(cc()); 
  11. console.log(cc()); 
  12. console.log(cc()); 
  13. console.log(a); 

 

责任编辑:华轩 来源: segmentfault
相关推荐

2011-05-12 18:26:08

Javascript作用域

2017-09-14 13:55:57

JavaScript

2016-09-14 09:20:05

JavaScript闭包Web

2010-06-29 08:39:25

Python闭包

2021-12-06 07:15:48

Javascript作用域闭包

2012-11-29 10:09:23

Javascript闭包

2021-10-26 13:18:52

Go底层函数

2020-12-16 11:09:27

JavaScript语言开发

2021-02-21 16:21:19

JavaScript闭包前端

2009-07-24 17:30:37

Javascript闭

2020-10-14 15:15:28

JavaScript(

2011-05-25 14:48:33

Javascript闭包

2023-11-26 00:34:36

Javascript应用方法

2009-10-26 09:41:26

PHP5.3闭包特性

2023-10-26 07:47:35

JavaScript代码变量

2016-09-18 20:53:16

JavaScript闭包前端

2010-06-23 10:24:42

Javascript闭

2023-09-06 16:55:33

JavaScript闭包

2022-10-24 08:08:27

闭包编译器

2011-03-02 12:33:00

JavaScript
点赞
收藏

51CTO技术栈公众号