刚刚总结完作用域链,我觉得很有必要马上对闭包总结一下,因为,之前也写过自己对闭包的理解,那时候只知道,闭包就是可以访问别的函数变量的函数,就是在函数里面的函数就叫做闭包,可是并没有深入探究,为什么,可以访问别的函数变量呢?直到,学习了JS的作用域链之后,就恍然大悟。

首先,来回顾一下,什么是作用域链吧。

作用域链就是由当前执行环境与上层环境的一系列变量对象组成,保证了当前执行环境对符合访问权限的变量和函数的有序访问。

那么什么是闭包呢?

闭包

关于闭包的定义,我在之前的文章里面已经讲过了,就是能够读取其它函数内部变量的函数,那么为什么闭包可以读取其它函数内部的变量呢?这里面就涉及到了作用域链

demo01
var fn = null;
function foo(){
var a = 2;
function innerFoo(){
console.log(a);
}
fn = innerFoo();
}
function Bar(){
fn();
}
foo();
Bar();

在这个例子里面,正常来说,按照作用域链的规则,在foo()函数的内部innerFoo()函数可以访问到,父级foo()的属性和方法,还有全局作用域下的属性和方法。这是因为,在innerFoo()的作用域链里面包含了fooECglobalEC的变量对象,所以有权限访问。

但是,之前讲过的垃圾回收机制提到,如果foo()方法执行完毕,应该释放内存,然后让垃圾回收机制回收,可是,为什么在Bar()里面依然能访问到fn()方法呢?

从上图可以看出,因为fn = innerFoo();这句语句,使得全局作用域下的变量fn保存了innerFoo()方法的引用,并且innerFoo()方法是依赖于foo()方法的,所以导致,foo()方法里面的局部变量都保存在了内存里面,没有被回收,这也是使用闭包不当的一个弊端,会导致内存泄漏

当执行Bar()方法的时候,Bar()的作用域链中包含了全局作用域下的变量对象,所以可以访问到foo()方法下的innerFoo(),这就是闭包的一个底层原理。

JS进阶系列之闭包的更多相关文章

  1. 【 D3.js 进阶系列 】 进阶总结

    进阶系列的文章从去年10月开始写的,晃眼又是4个多月了,想在年前总结一下. 首先恭祝大家新年快乐.今年是羊年吧.前段时间和朋友聊天,聊到十二生肖里为什么没猫,我张口就道:不是因为十二生肖开会的时候猫迟 ...

  2. 【 D3.js 进阶系列 — 4.0 】 绘制箭头

    转自:http://www.ourd3js.com/wordpress/?p=660 [ D3.js 进阶系列 — 4.0 ] 绘制箭头 发表于2014/12/08 在 SVG 绘制区域中作图,在绘制 ...

  3. 【 D3.js 进阶系列 — 1.1 】 其它表格文件的读取

    CSV 表格文件是以逗号作为单元分隔符的,其他还有以制表符 Tab 作为单元分隔符的 TSV 文件,还有人为定义的其他分隔符的表格文件.本文将说明在 D3 中怎样读取它们. 1. TSV 表格文件是什 ...

  4. 【 D3.js 进阶系列 — 1.2 】 读取 CSV 文件时乱码的解决方法

    在 D3 中使用 d3.csv 读取 CSV 文件时,有时会出现乱码问题. 怎么解决呢? 1. 乱码问题 使用 d3.csv 读取 xxx.csv 文件时.假设 xxx.csv 文件使用的是 UTF- ...

  5. JS进阶系列之作用域链

    在之前写的进阶系列里面,提到了执行上下文在创建阶段,要创建变量对象.确定作用域链还有确定this的指向,本次将重点讲解一下作用域链. JavaScript代码的执行过程 在讲解作用域链之前,首先了解一 ...

  6. JS进阶系列之内存空间

    也许很多人像我一样,觉得JS有垃圾回收机制,内存就可以不管了,以至于在全局作用域下定义了很多变量,自以为JS会自动回收,直到最近,看了阮一峰老师,关于javascript内存泄漏的文章时,才发现自己写 ...

  7. 【 D3.js 进阶系列 — 6.1 】 缩放的应用(Zoom)

    缩放(Zoom)是另一种重要的可视化操作,主要是使用鼠标的滚轮进行. 1. zoom 的定义 缩放是由 d3.behavior.zoom() 定义的. var zoom = d3.behavior.z ...

  8. 【 D3.js 进阶系列 — 2.1 】 力学图的事件 + 顶点的固定

    本章讨论在力学图中经常使用到的事件( Event ),然后对[p=555">进阶 - 第 2.0 章]的人物关系图进行改进.使用户可以固定拖拽的对象. 在[入门 - 第 9.2 章]和 ...

  9. 【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取

    在入门系列的教程中.我们经常使用 d3.json() 函数来读取 json 格式的文件.json 格式非常强大.但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 O ...

随机推荐

  1. 时分秒倒计时的js实现

    示例: 剩余天数:08天02事02分02秒 html代码: <div id="timer" data-timer="20160628140203" sty ...

  2. python 定时器schedule执行任务

    import schedule import time """英文版书籍:<essential sqlalchemy>,这本书讲了很多在每天某个指定的时间点上 ...

  3. Spring事务(二)事务自定义标签

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.注册 InfrastructureAdvisorAutoPr ...

  4. openstack placement 组件作用理解

    例如,一个资源提供者可以是一个计算节点,共享存储池,或一个IP分配池.placement服务跟踪每个供应商的库存和使用情况.例如,在一个计算节点创建一个实例的可消费资源如计算节点的资源提供者的CPU和 ...

  5. 安装framework 4.6.2的时报错 “无法建立到信任根颁发机构的证书链”

    解决方案: 1.下载证书:MicrosoftRootCertificateAuthority2011.cer 2.开始→运行→MMC 3.文件→添加删除管理单元 (Ctrl+M) 4.证书→计算机账户 ...

  6. PHP+MySQL实现海量数据导入导出的总结:is_numbric函数的坑

    前段时间有个需求:将生产环境的部分数据转移到测试服务器进行测试.由于只需要导入特定账号的数据,我就想着将写个脚本,将数据组装成sql语句导出为sql文件,然后转移到测试服务器,导入到MySQL中.想象 ...

  7. hbase-列存储动态数据库

    1)   HBase是什么? HBase是建立在Hadoop文件系统之上的分布式面向列的数据库.它是一个开源项目,是横向扩展的. HBase是一个数据模型,类似于谷歌的大表设计,可以提供快速随机访问海 ...

  8. Word里面怎么取消全文每个标题前面都有的这个点

    Word里标题前面的那个点,如图1所示看起来觉得很不舒服,该怎么把它取消呢?(本测试环境是Win 10 64位系统,Microsoft Office家庭和学生版 2016) 图1 选中所有标题,如图2 ...

  9. Oracle 循环插入测试数据(网上收集整理)

    一 Oracle 循环插入测试数据 declare          maxrecords constant int:=1000;          i int :=1; begin for i in ...

  10. JavaWeb总结(三)

    什么是Servelt - 是运行在Web服务器或应用服务器上的Java程序 - 在Web上创建动态内容的有效而强大的解决方案 - 由容器来管理生命周期与Web服务器交互 Servlet规范的组成 Ja ...