理解JS闭包
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解。欢迎大牛拍砖吐糟
理解JS中的闭包,首先理解JavaScript中的作用域以及作用域链的问题,可以参考下我的拙见JS函数作用域及作用域链理解。
什么是闭包
学术说法:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。(你能看懂吗?反正我不能)
专业说法:函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内。(这个你懂吗?我略懂)
通俗说法:所有JavaScript函数都是闭包,因为函数都是对象,都关联到作用域,并且变量都保存在函数作用域内。(这个有点扯,困惑我的闭包,就这么简单)
但是我们通常说的闭包是当一个函数嵌套另一个函数,外部函数将嵌套函数对象作为返回值返回的时候,我们把这种情况称为闭包。
看下面一个例子
function func() {
var num = 0; //声明局部变量:num
function f() { //嵌套函数,在作用域里
console.log(++num)
}
return f(); //调用嵌套函数f,并将f的执行结果返回
}
func(); //输出:1
函数func()声明了一个局部变量,并定义了一个函数f(),最后将函数f()的执行结果返回。很容易理解输出结果为1。现在我们将这段代码稍作改动,如下面
function func() {
var num = 0; //声明局部变量:num
function f() { //嵌套函数,在作用域里
console.log(++num)
}
return f; //调用嵌套函数f,并将f的执行结果返回
}
var ff = func();
ff(); //输出:1
ff(); //输出:2
ff(); //输出:3
现在函数func()仅仅返回函数内嵌套的一个函数对象,而不是直接返回结果。在定义函数作用域外面调用嵌套函数,由于这个函数的作用域链是在函数定义的时候就已经创建的。嵌套的函数f()定义在这个作用域链里,并且变量num又是局部变量,不管在何时何地执行函数f(),这种绑定依然有效。因此,局部变量会一直保存下来。正式因为闭包的这一强大特性,才是其显得非常重要。
闭包实现
当一个函数func()创建后,它保存了一个作用域链,并且作用域链会被函数func()中的作用域中可访问的数据对象num填充。
执行此函数func()时会创建一个称为“运行期上下文(execution context)”的内部对象,运行期上下文定义了函数执行时的环境。并且运行期上下文对应自己的作用域链,同时它的作用域链初始化为当前运行函数func()的[[Scope]]所包含的对象。
然后执行环境会创建一个活动对象(call object),用来报讯局部变量,并把这个对象添加至作用域链[[Scope]]中。假如不存在嵌套函数,也没有其他引用的时候,活动对象就会被当做垃圾回收掉。但是这里有嵌套函数f(),并将函数f()作为返回值返回时,就会又一个外部引用指向这个嵌套函数f(),活动对象就不会当做垃圾回收掉,并且活动对象指向的变量所绑定的对象也不会被回收。
理解JS闭包的更多相关文章
- javascript深入理解js闭包(转)
javascript深入理解js闭包 转载 2010-07-03 作者: 我要评论 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...
- 理解JS闭包的几个小实验
学了JavaScript有一段时间了,但是对闭包还是不太理解,于是怀着心中的疑问做了几个小实验,终于有点明白了. 首先看一下MDN上的定义:闭包是函数和声明该函数的词法环境的组合. 简单来说,闭包是一 ...
- javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- 深入理解JS闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- 通俗易懂的深入理解js闭包
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...
- 理解js闭包(二)
@(编程) 一.什么是闭包? 官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 相信很少有人能直接看懂这句话,因为他 ...
- javascript深入理解js闭包[转]
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- (转)javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- javascript深入理解js闭包(个人理解,大神勿喷)
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
随机推荐
- tcp/心跳包
1,http://blog.csdn.net/yuzhiyuxia/article/details/7857508 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时 ...
- Makefile与shell脚本区别
http://blog.chinaunix.net/uid-20672257-id-3345593.html 在Makefile可以调用shell脚本,但是Makefile和shell脚本是不同的.本 ...
- 聚类算法初探(六)OPTICS
最近由于工作需要,对聚类算法做了一些相关的调研.现将搜集到的资料和自己对算法的一些理解整理如下,供大家参考. 另外在算法代码方面,我也做了一些实现(包括串行和并行),欢迎感兴趣的朋友探讨和交流. 第一 ...
- oracle em命令行配置及界面按钮乱码问题解决方法
一.配置EM dbconsole db [oracle@rusky ~]$ lsnrctl start [oracle@rusky ~]$ emctl start dbconsoleTZ set to ...
- RDLC报表系列(五) 简单的图表-柱状图
继续接上一篇的内容,本文主要是讲图标的内容,本文就是简单的图标,复杂的柱状图和折线图在下一文章中介绍. 数据源还是上文RDLC报表系列(四) 矩阵中的相同 1.还是继续使用demo2的文件
- linux下Java环境的配置
linux下Java环境的配置 现在用linux的朋友越来越多了,前几天就有两个朋友问我linux下怎么配置java环境,我想还有很多朋友想了解学习这方面的东西,就写一个完全一点的linux java ...
- C# 对XML基本操作总结
C# 对XML基本操作包括读取节点的数据,添加节点.读取节点属性,修改节点属性等.具体如下: XML文件:文件在MyDocument文件夹下 <?xml version="1.0&qu ...
- STM32学习笔记之一(初窥STM32)
怎么做好学习笔记? 答:自我感知-->学习知识-->归纳总结-->自我升华(真正属于自己的知识是,抛开书本,运用时,你还能记得的思想) 自我感知--看到知识概念,先自我感觉那应该是个 ...
- mysql 蠕虫复制
INSERT into user_info(version,create_user_count,create_pc_count) select version,create_user_count,cr ...
- Nginx提示502和504错误的终极解决方案
将脚本添加至计划任务: /usr/local/php/sbin/php-fpm reload 直接在crontab里写入php-fpm的平滑重启命令,"平滑重启"和" ...