JS中的闭包是一个看着好像不难,但又很容易搞糊涂的东西,相信很多人都是和我一样似懂非懂,这次我们从最实用的角度来研究一下这个问题。

1.闭包是什么

根据MDN给出的定义:

函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure),也就是说,闭包可以让你从内部函数访问外部函数作用域
解释一下这里的词法环境,指的也就是我们常说的上下文。我们来看一个例子:

function init() {var name = "Mozilla"; // name 是一个被 init 创建的局部变量function displayName() { // displayName() 是内部函数,一个闭包alert(name); // 使用了父函数中声明的变量}displayName();
}
function getName(){console.log(name);
}init()//alert("Mozilla")
getName()//name is not defined

在displayName这个函数内部,并没有name变量,但是它所处的词法环境,也就是外部函数init内部有一个name变量,因此可以在displayName中使用这个变量,这正是因为函数displayName中有对词法环境的引用。而在没有这个引用的getName中,则不能使用name变量.

再看第二个例子:闭包由函数

function makeFunc() {var name = "Mozilla";function displayName() {console.log(name);}return displayName;
}
var myFunc = makeFunc();
myFunc();

与上面的例子不同的是,这个makeFunc函数的返回值是一个还没有执行的函数。当我们执行myFunc时可以正常打印name的值,这说明displayName这个函数将makeFunc这个环境中的变量name带到了外部,进一步证明了displayName中含有指向自身词法环境的引用。

总结一下就是:

函数A内部有函数B,则在函数B中有对A内部环境的引用,所以在B中可以访问创建B时A中的所有变量,而在函数A外部则不可以访问A中的变量。在A中将B作为返回值,则返回的函数B以及函数B中对于A内部环境的引用构成了闭包

2.闭包用来干什么

通过上面的定义我们已经可以回答这个问题,闭包的存在可以让函数使用其外部函数中的变量。

不过听上去好像没什么用。那么闭包有什么实际价值呢?

我们知道,在传统的面向对象语言如java中,类会有自己的私有成员,在外部无法访问,但在JS中并不存在这种机制,无论是通过class定义类,或是通过构造函数定义对象,都没有私有变量一说,而通过闭包我们就可以完成私有变量的定义。

再看一个例子:

function number(){var num=0;function add(){num++;}function dec(){num--;}function val(){return num;}return{add:add,dec:dec,val:val}
}
var Num=number();
console.log(Num.num);//undefined
Num.val();//0
Num.add();
Num.val();//1
Num.dec();
Num.val()//0

可见,通过这种方法实现了私有变量,在外部无法访问Num的num成员,只能通过预留的函数接口对其进行操作和访问。

所以,在任何需要进行数据隐藏和封装的地方,都可以用上闭包

注意:

在前面我们说到了,内部函数中的引用,指向的时创建该函数时的词法环境,也就是说,如果在后面这个词法环境改变了,这个引用所指向的内容会与直觉不符。因此,在闭包中要避免使用后续会变化的一切变量。其中最常见的,如循环变量。
闭包对于性能有负面影响。若非需要,不要使用

【闭包】JS的闭包到底是什么相关推荐

  1. Jquery真的不难~第八回 JS的闭包问题

    百度百科中对闭包的定义: 闭包是可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义."闭包" 一词来源 ...

  2. 带你一分钟理解闭包--js面向对象编程

    什么是闭包? 先看一段代码: function a(){var n = 0;function inc() {n++;console.log(n);}inc(); inc(); } a(); //控制台 ...

  3. 函数的实参 函数的形参 闭包 js

    函数的实参和形参 可选形参 if(a === undefined) a = []; 等价于 a = a || []; 这两句是完全等价的,只不过后者需要提前声明a而已 如果参数没有传入,其余的填充un ...

  4. 利用js的闭包原理做对象封装及调用方法

    创建一个js文件,名为testClosure.js: ? 1 2 3 4 5 6 7 8 9 (function () {   function a()   {     alert('i am a') ...

  5. 函数的实参 函数的形参 闭包 js 1

    函数的实参和形参 可选形参 if(a === undefined) a = []; 等价于 a = a || []; 这两句是完全等价的,只不过后者需要提前声明a而已 如果参数没有传入,其余的填充un ...

  6. 理解闭包 js回收机制

    为什么要有回收机制?why? 打个比方,我有一个内存卡,这个内存是8G的,我把文件,视频,音乐,都保存到了这个内存卡,随着我的储存的内容越来越多,这个内存卡已经保存不了了,如果我还想再把其他的文件保存 ...

  7. 离散数学,Js 中闭包的解释和联系

    总共分三部分说明闭包问题: (1)部分  转发自: https://blog.csdn.net/wzwdcld/article/details/44783459,如侵权,请告知删除. 二元关系  设S ...

  8. 作用域链和闭包?JS引擎如何选择顺序的选择变量?

    前言 前面的博客我已经说完了块级作用域的实现,站在变量环境和词法环境的角度下去看待这些个问题,会让你对js的工作模式有更加清晰的认识. 接下来我们看一段代码 function bar() {conso ...

  9. 从λ演算到函数式编程聊闭包(1):闭包概念在Java/PHP/JS中形式

    什么是闭包 如果让谷哥找一下"闭包"这个词,会发现网上关于闭包的文章已经不计其数 维基百科上对闭包的解释就很经典: 在计算机科学中,闭包(Closure)是词法闭包(Lexical ...

  10. 什么是闭包,对闭包的理解,闭包的用途及优缺点

    1.对闭包的理解         闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量. 2.闭包的特点 1.让外 ...

最新文章

  1. 邮件MIME格式分析
  2. static_cast
  3. SQL 必知必会·笔记14更新和删除数据
  4. Linux中英文命令对应
  5. Spring 框架基础(05):事务管理机制,和实现方式
  6. winxp制作服务器,你要知道的WinXP服务器操作系统安装的方法
  7. 7类数据分析常见的统计陷阱,快来排雷!
  8. [Python]网络爬虫学习笔记,爬取豆瓣妹子上妹子的照片
  9. 三相并网逆变器PI控制——离网模式
  10. 最全的国内外电子书籍网站合集
  11. 计算机网络对社会发展的影响
  12. Elasticsearch5.3 JAVA Demo 聚合查询
  13. JAVA笔试题笔记(二)
  14. MvvmLazy Android懒人框架
  15. 在金山云上,“雷布斯”有这些野心
  16. Snipaste截图时下拉菜单消失解决方法
  17. FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用
  18. leetcode-第六题 Z 字形变换
  19. 第二章 大教堂与市集
  20. ​Excel如何转换成Word文档?教你如何实现转换

热门文章

  1. 拔得头筹 | 阿里云混合云荣膺IPv6最佳实践奖
  2. 特别好用的录屏软件--ZD Soft Screen Recorder_8.0
  3. 文献学习记录|事件触发模型预测自适应动态编程用于无人驾驶地面车辆的道路交叉口路径规划
  4. 辽宁聚能合创:抖音直播赚钱吗?
  5. 计算机软件实习(一)简单计算机
  6. vertx instance
  7. 简单音乐铃声(接口版)
  8. 第一台兼容计算机,如何配置一台兼容台式电脑——计算机基础
  9. java 最大矩形_Java练习 SDUT-2401最大矩形面积
  10. Spring Boot 使用 Kotlin Script Template 模板引擎kts 开发web应用