深入理解JavaScript系列:试着谈谈闭包
闭包可能是JavaScript里最被人神乎其神的一个概念,世间万物皆凡夫俗子,你觉着他神奇是因为你根本没有了解,所有的事物当你了解透彻后就不会有这种不明觉厉的错觉了。哈哈哈,上来又是一顿哲学普及。
下面开始进行阐述。
1.什么是闭包?
参阅了很多资料,最后比较靠谱的解释就是“闭包是一个函数”。
闭包是一个函数,什么样的函数才能叫做闭包?可以从他的作用上理解闭包就是能够读取其他函数内部变量的函数。
2.闭包是怎么形成的?
首先再回顾下JavaScript的作用域这个概念。JavaScript是函数作用域而不是块状作用域,也就是说JavaScript的作用域是以函数来划分的,函数内部的变量为私有变量,而相对的全局变量是指在所有的函数外部定义的变量。全局变量自动归为全局对象global的属性,在web浏览器中这个global对象由window对象来承担这个全局变量的角色。
一般的,在函数内部声明的加了var声明符的(函数内部定义变量不加var的话会默认声明为全局变量,为了避免全局空间变量污染所以要谨记)变量,在这个函数执行时候创建该函数相关的作用域,函数当然会有嵌套,所以就会存在作用域链接作用域的问题,也就是所说的作用域链。这个作用域链从最里层函数作用域开始,逐渐向外层链接,一层一层直到最外层的全局作用域。所以在内层的函数使用某个变量的时候会按照这个链接顺序去寻找,如果中途找到则停止,直到全局作用域还没有找到则该变量为未定义。
正常情况,一个函数在调用开始执行时创建这个函数执行上下文及相应的作用域链,在函数执行结束后释放函数执行上下文及相应作用域链所占的空间。
明白了作用域后再来看闭包怎样才能读取到其它函数的内部变量这个问题。首先,如果是函数A嵌套函数B,函数B自然可以访问函数A里的变量,向上还可以直到全局作用域的变量。这种情况肯定形成不了闭包。所以闭包是在某函数A之外的函数B想要访问函数A内部的变量下形成的。
3.闭包怎么样才能读取到其它函数的内部变量?
最常见的形式就是在函数内部返回一个函数,这个返回的函数有引用外部函数的变量。示例代码如下:
function foo() {
var tmp = 0;
return function () {
console.log(tmp = tmp + 1);
}
}
var bar = foo(); // foo()执行后返回内部匿名函数,所以bar现在就是内部的那个函数的引用
bar(); //现在执行bar,也就是执行内部的那个匿名函数,输出为1,
bar(); //紧接着再执行bar,输出为2,也就是说foo函数内部的tmp变量不仅被外部的函数访问到了,而且tmp的值没有被清空,会累加
这就满足了形成闭包的条件,即相对函数A(这里指foo())而言他外部的函数B(这里指bar(),其实bar只是内部匿名函数的引用在外部执行)访问到了A作用域的变量tmp,而且值的注意的是tmp变量一直存在于内存中。
依据上边这段代码解释为什么变量会一直存在于内存中而不是随着函数执行完毕后就被垃圾回收。
首先,bar是在外部作用域中,大部分时候是在全局作用域中,而全局作用域中的变量是一直存在于内存中的,所以当bar引用foo的时候,间接地foo也会一直存在于内存中,既然foo都一直存在于内存中,那foo所形成的函数作用域里的一切都会一直存在于内存中,因此就会出现上边看到的访问到的内部变量不会随着函数执行完后进行垃圾回收的情况。
4.怎样才能理解闭包?
首先明白他是一个能访问其它函数内部作用域变量的函数,打破了常规的函数作用域的限制,再理解就是他引用的变量会一直存在于内存中。
下面贴一些闭包的代码,都是从其他地方看到的:
var object = {
a: 1,
getA: function () {
console.log(this.a=this.a+1);
}
}
object.getA();//输出为2
object.getA();//输出为3
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
5.闭包都有什么用处?
深入理解JavaScript系列:试着谈谈闭包的更多相关文章
- 深入理解JavaScript系列(16):闭包(Closures)
介绍 本章我们将介绍在JavaScript里大家经常来讨论的话题 —— 闭包(closure).闭包其实大家都已经谈烂了.尽管如此,这里还是要试着从理论角度来讨论下闭包,看看ECMAScript中的闭 ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- 深入理解JavaScript系列
转自http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 深入理解JavaScript系列(1):编写高质量JavaScript代码 ...
- [JS]深入理解JavaScript系列(4):立即调用的函数表达式
转自:汤姆大叔的博客 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行.在详细了解这个之前,我们来谈了解一下"自执行"这个叫法 ...
- 深入理解JavaScript系列(转自汤姆大叔)
深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...
- [转]深入理解JavaScript系列
文章转自:汤姆大叔-深入理解JavaScript系列文章 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解Ja ...
- [转载]深入理解JavaScript系列 --汤姆大叔
深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...
- 深入理解JavaScript系列(转载)
深入理解JavaScript系列 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaSc ...
- 深入理解JavaScript系列(49):Function模式(上篇)
介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying) ...
- 深入理解JavaScript系列(47):对象创建模式(上篇)
介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...
随机推荐
- Python’s SQLAlchemy vs Other ORMs[转发 7] 比较结论
Comparison Between Python ORMs For each Python ORM presented in this article, we are going to list t ...
- 面试中常用的__proto__,prototype和原型链,你都了解了吗?
上一篇随笔主要讲了变量提升的问题,今天我们来讲讲很多前端er在初期很长一段时间内都没有完全搞明白的原型链和构造函数. 1,什么是构造函数 那么要讲到构造函数,必须要有一个函数,所以我们建立一个函数 f ...
- thinkPHP的用法之创建新项目
1 配置文件中 新增数组元素:'DEFAULT_APPS'=> array('api', 'admin', 'home', 'megagame'), 2 新增样式变量 在view.class.p ...
- zend create project prepare
1.php ini 安装pear 设置include_path 2.apache AllowOverride LoadModule rerwite去掉注释 <VirtualHost *:> ...
- HDMI之CEC DDC学习笔记(可能有误)
1 HDMI的音视频通路,有待学习: 2 DDC通路,大致是个IIC接口,读取上游器件的EDID或者E-EDID数据: EDID的前128字节数据格式如下:(可能有不同版本,格式可能有区别)
- angularJs|es6|reactJs|vueJs相关技术(请访问https://expendo.github.io/)
技术博客地址:https://expendo.github.io/
- struts2+spring+hibernte整合示例
简单实现添加用户功能,仅供初学者参考,可自行扩展程序功能(增删改查). 这里贴下代码,需要的可以下载看(因为比较懒). applicationContext.xml <?xml version= ...
- Spring Boot中的注解
文章来源:http://www.tuicool.com/articles/bQnMra 在Spring Boot中几乎可以完全弃用xml配置文件,本文的主题是分析常用的注解. Spring最开始是为了 ...
- php上传文件类型
下面提供一张IE和火狐浏览器的文件类型对照表: ie 火狐 id 后缀名 php识别出的文件类型 0 gif image/gif 1 jpg image/jpeg 2 png image/png 3 ...
- windows8.1下android开发环境搭建(Eclipse+Android sdk+ADT+Genymotion)
一.基本jdk.eclipse环境 二.android sdk 1.下载安装:https://developer.android.com/sdk/installing/index.html?pkg=t ...