JavaScript 闭包详细介绍


Posted in Javascript onSeptember 28, 2016

深入理解JavaScript——闭包

跟很多新手一样我也是初入前端,对闭包的理解花费的时间和精力相当的多。效果也还行,今天我就来根据自己的理解细致的讲一讲闭包,由于是初入学习的时候不免有一些弯路和困惑,我想信这也是很多跟我一样的人会同样遇到的问题。我就以自己的学习路径和遇到的各种坑来谈闭包。希望对各位有一定的帮助。(菜鸟,也请各位多多指教)

闭包是什么?《JavaScript高级程序设计》上面这么描述的:闭包是指有权访问另一个函数作用域中的变量的函数。这句话第一次看的时候模模糊糊,似是而非。碰到问题就不会运用了,听别人的分析头头是道,说到底还是没搞明白。现在我觉得要彻底搞清这句话必须对JavaScript的作用域,匿名函数,甚至JavaScript的编译原理有一些简单的了解。经过查阅理解各种资料书籍对闭包的解释,再回过头来看了一些源码,慢慢的有了一点感觉。我觉得对闭包描述最好的一句话是:“闭包是基于词法作用域书写代码时所产生的自然结果,你甚至不需要为了利用它而有意为之的创建闭包,闭包的创建和使用是在你的代码中随处可见。你缺少的是根据你自己的意愿来识别,拥抱和影响闭包的思维环境。”话有点长但点出来闭包在JavaScript这么语言中存在的实际价值,大家可以细细体会一下。接下来我已实际例子来讲讲闭包。

首先看一个简单的例子:

function createComparisonFunction(propertyName){
  return function(obj1,obj2){

var value1=object1[propertyName];


var value2=object2[propertyName];


if(value1<value2){



return -1;


}else if(value1>value2){



return 1;


}else{



return 0;


}

} 
}

例子中返回的是一个匿名函数,其中匿名函数中value1,value2同时又对外部函数createComparisonFunction()的参数propertyName进行调用。再看看上面对闭包的定义:有权访问另一个函数作用域中的变量的函数。return的匿名函数有权访问外部函数作用域中的变量propertyName,因此这是一个闭包。但实际来说这只是一个基于词法作用域的查找规则,很好理解也很自然。

可能有些人不明白什么是词法作用域的查找规则:其实说简单点就是根据变量的作用链域来查找并取得该变量。以上例来说:createComparisonFunction函数的作用域包含一个变量property和一个匿名函数(由于没有函数名其实在createComparisonFunction函数中也无法调用,这也是匿名函数的一个缺点,记得事件监听函数调用一个匿名函数时是无法移除吗?道理是一样的),匿名函数作用域中包括obj1,obj2,value1,value2这四个变量。匿名函数中的变量调用时首先在自己作用域中查询,找到了该变量就调用,找不到就往外层走接着找,直到全局作用域如果还是找不到就会报ReferenceError(如果找到了一个var a;呢?由于a为undefined所以会报TypeError)。而createComparisonFunction函数则只能在他的作用域中查找,不能去内层的匿名函数中查找,这种查找规则就是词法作用域的查找规则(当然这不只是基本规则)。

 我们再来看一个例子:

function foo() {
var a = 2;

function bar() {


console.log( a );

}

return bar;
}
var baz = foo();
baz();
//2

答案可能很多人都能猜出来但其实现原理是怎样呢?我现在就来细致的分析一下:首先声明了一个函数foo其作用域包括变量a和bar函数。foo函数内部有一个函数bar内部没有新变量。然后定义一个变量baz,其值为foo()而foo()返回bar,顾baz=bar;最后一句baz()即等价于bar();根据词法作用域的规则bar是在foo函数中声明的。外部是无法访问的呀!这正是闭包的神奇之处!我们再一次回到闭包定义:有权访问另一个函数作用域中的变量的函数,baz()函数有权访问foo函数中的bar。这就是闭包对吧!搞清闭包后有些人还会疑问?闭包是怎么形成的,为什么你说它有权访问foo中的bar呢?首先闭包的形成是在一个函数内部创建一个函数这是创建闭包的最常见方法。当将内部函数传递到它的词法作用域以外他都会持有对原始定义作用域的引用,执行此函数就会 使用闭包。

闭包的基础大概就是这几点,希望大家能仔细体会。抽时间补充点闭包的一些其他用途,来帮大家扩展一下思维。

        通过此文,希望大家对闭包的知识掌握,谢谢大家对本站的支持!

Javascript 相关文章推荐
简单通用的JS滑动门代码
Dec 19 Javascript
RGB颜色值转HTML十六进制(HEX)代码的JS函数
Apr 25 Javascript
同一个表单 根据要求递交到不同页面的实现方法小结
Aug 05 Javascript
点击文章内容处弹出页面代码
Oct 01 Javascript
JS在IE和FireFox之间常用函数的区别小结
Mar 12 Javascript
jquery判断当前浏览器的实现代码
Nov 07 Javascript
JS遍历数组和对象的区别及递归遍历对象、数组、属性的方法详解
Jun 14 Javascript
用JS实现图片轮播效果代码(一)
Jun 26 Javascript
Bootstrap的class样式小结
Dec 01 Javascript
在javascript中,null>=0 为真,null==0却为假,null的值详解
Feb 22 Javascript
jQuery输入框密码的显示隐藏【代码分享】
Apr 29 jQuery
代码块高亮可复制显示js插件highlight.js+clipboard.js整合
Feb 15 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
Sep 28 #Javascript
bootstrap datepicker限定可选时间范围实现方法
Sep 28 #Javascript
BootstrapValidator不触发校验的实现代码
Sep 28 #Javascript
bootstrap datepicker 与bootstrapValidator同时使用时选择日期后无法正常触发校验的解决思路
Sep 28 #Javascript
使用bootstrapValidator插件进行动态添加表单元素并校验
Sep 28 #Javascript
BootStrap 动态添加验证项和取消验证项的实现方法
Sep 28 #Javascript
Javascript中判断一个值是否为undefined的方法详解
Sep 28 #Javascript
You might like
php实现文件下载简单示例(代码实现文件下载)
2014/03/10 PHP
php两种无限分类方法实例
2015/04/21 PHP
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
2010/04/27 Javascript
jquery实现文本框鼠标右击无效以及不能输入的代码
2010/11/05 Javascript
在标题栏显示新消息提示,很多公司项目中用到这个方法
2011/11/04 Javascript
jquery 年会抽奖程序
2011/12/22 Javascript
JavaScript中检测变量是否存在遇到的一些问题
2013/11/11 Javascript
wap浏览自动跳转到wap页面的js代码
2014/05/17 Javascript
Node.js中安全调用系统命令的方法(避免注入安全漏洞)
2014/12/05 Javascript
Javascript基础教程之while语句
2015/01/18 Javascript
jQuery设置和移除文本框默认值的方法
2015/03/09 Javascript
微信小程序 数据交互与渲染实例详解
2017/01/21 Javascript
jQuery Masonry瀑布流布局神器使用详解
2017/05/25 jQuery
浅析node Async异步处理模块用例分析及常用方法介绍
2017/11/17 Javascript
在vue中给后台接口传的值为数组的格式代码
2020/11/12 Javascript
javascript实现拼图游戏
2021/01/29 Javascript
python opencv3实现人脸识别(windows)
2018/05/25 Python
Python文件如何引入?详解引入Python文件步骤
2018/12/10 Python
selenium中get_cookies()和add_cookie()的用法详解
2020/01/06 Python
python-sys.stdout作为默认函数参数的实现
2020/02/21 Python
Pytorch使用PIL和Numpy将单张图片转为Pytorch张量方式
2020/05/25 Python
获取python运行输出的数据并解析存为dataFrame实例
2020/07/07 Python
Python尾递归优化实现代码及原理详解
2020/10/09 Python
Python数据可视化常用4大绘图库原理详解
2020/10/23 Python
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
澳大利亚100%丝绸多彩度假装商店:TheSwankStore
2019/09/04 全球购物
我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。 为什么如下的代码((int *)p)++; 不行?
2013/05/09 面试题
中专三年学习的个人自我评价
2013/12/12 职场文书
公交公司毕业生求职信
2014/02/15 职场文书
寄语是什么意思
2014/04/10 职场文书
物理学专业自荐信
2014/06/11 职场文书
师德师风整改措施
2014/10/24 职场文书
学生保证书
2015/01/16 职场文书
教师“一帮一”结对子活动总结
2015/05/07 职场文书
SQL Server 忘记密码以及重新添加新账号
2022/04/26 SQL Server
python index() 与 rindex() 方法的使用示例详解
2022/12/24 Python