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 相关文章推荐
图片之间的切换
Jun 26 Javascript
用javascript getComputedStyle获取和设置style的原理
Oct 10 Javascript
jQuery Div中加载其他页面的实现代码
Feb 27 Javascript
对 lightbox JS 图片控件进行了一下改造, 使其他支持复杂的图片说明
Mar 20 Javascript
JavaScript实现两个Table固定表头根据页面大小自行调整
Jan 03 Javascript
jquery操作angularjs对象
Jun 26 Javascript
jquery获取img的src值的简单实例
May 17 Javascript
微信小程序  http请求封装详解及实例代码
Feb 15 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 Javascript
vue使用ajax获取后台数据进行显示的示例
Aug 09 Javascript
vue fetch中的.then()的正确使用方法
Apr 17 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
Nov 16 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
虫族 Zerg 历史背景
2020/03/14 星际争霸
轻松入门: 煮好咖啡的七个诀窍
2021/03/03 冲泡冲煮
用PHP读注册表
2006/10/09 PHP
关于PHP中的Class的几点个人看法
2006/10/09 PHP
PHP写的获取各搜索蜘蛛爬行记录代码
2012/08/21 PHP
PHP处理JSON字符串key缺少双引号的解决方法
2014/09/16 PHP
php+mysqli使用面向对象方式更新数据库实例
2015/01/29 PHP
PHP与Java对比学习日期时间函数
2016/07/03 PHP
PHP实现带重试功能的curl连接示例
2016/07/28 PHP
php生成二维码图片方法汇总
2016/12/17 PHP
js 数组操作代码集锦
2009/04/28 Javascript
DOM下的节点属性和操作小结
2009/05/14 Javascript
jQuery 可以拖动的div实现代码 脚本之家修正版
2009/06/26 Javascript
javascript移出节点removeChild()使用介绍
2014/04/03 Javascript
js实现的类似于asp数据字典的数据类型代码实例
2014/09/03 Javascript
jQuery中:text选择器用法实例
2015/01/03 Javascript
js实现跨域的多种方法
2015/12/25 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
微信小程序 列表的上拉加载和下拉刷新的实现
2017/04/01 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
微信小程序实现YDUI的ScrollTab组件
2018/02/02 Javascript
Vue.js+Layer表格数据绑定与实现更新的实例
2018/03/07 Javascript
[01:57]2018DOTA2亚洲邀请赛赛前采访-iG
2018/04/03 DOTA
Python写的Discuz7.2版faq.php注入漏洞工具
2014/08/06 Python
python创建和删除目录的方法
2015/04/29 Python
python直接访问私有属性的简单方法
2016/07/25 Python
Python编程实现生成特定范围内不重复多个随机数的2种方法
2017/04/14 Python
python实现微信自动回复及批量添加好友功能
2019/07/03 Python
Python loguru日志库之高效输出控制台日志和日志记录
2020/03/07 Python
django ObjectDoesNotExist 和 DoesNotExist的用法
2020/07/09 Python
size?瑞典:英国伦敦的球鞋精品店
2018/03/01 全球购物
领导干部廉政自律承诺书
2014/05/26 职场文书
运动会闭幕式主持词
2015/07/01 职场文书
高考百日冲刺决心书
2015/09/23 职场文书
Python数据分析入门之教你怎么搭建环境
2021/05/13 Python
利用Python第三方库实现预测NBA比赛结果
2021/06/21 Python