2014-11-4

闭包

闭包是指有权访问另一个函数作用域中变量的函数。创建闭包的方式:在一个函数内部创建另一个函数。

function a(){
	var i=0;
	function b(){
		var x=0;
		alert(i++);
	}
	return b;
}
var c=a();
c();//0
c();//1
c();//2
c();//3
c();//4
c();//5

这段代码有两个特点:

  1、函数b嵌套在函数a内部;

  2、函数a返回函数b。

  这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:

  当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

  我猜想你一定还是不理解闭包,因为你不知道闭包有什么作用,下面让我们继续探索。

  二、闭包有什么作用?

  简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的 执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。

在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。

  那 么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。(关于Javascript的垃圾回收机制将在后面详细介绍)

  三、闭包内的微观世界

  如 果要更加深入的了解闭包以及函数a和嵌套函数b的关系,我们需要引入另外几个概念:函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。

  1、当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。

  2、当函数a执行的时候,a会进入相应的执行环境(excution context)。

  3、在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。

  4、然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a 的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。

  5、下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。

  6、最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。

  到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。

  当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示:

  如图所示,当在函数b中访问一个变量的时候,搜索顺序是先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依 次查找,直到找到为止。如果整个作用域链上都无法找到,则返回undefined。如果函数b存在prototype原型对象,则在查找完自身的活动对象 后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。

  四、闭包的应用场景

  1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。

  2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。

  以上两点是闭包最基本的应用场景,很多经典案例都源于此。

  五、Javascript的垃圾回收机制

  在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

javascript中关于函数内部变量的调用方法(闭包)

闭包(closure)是Javascript的特色,很多高级应用都要依靠闭包实现。
      首先必须理解Javascript变量作用域。全局变量和局部变量。函数内部能够读取全局变量,但是在外部无法读取函数内部变量。而闭包就是解决外部得到函数内的局部变量。

闭包的用途
1、读取函数内部的变量;
2、让函数内部的变量的值始终保持在内存中。

在下面的代码中我将详细说明闭包的用法和我的一些理解

<!DOCTYPE html>
<html>
<head>
    <title>javascript中关于函数内部变量的调用方法(闭包)</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
     <script type="text/javascript">
         function house(){
             var num=1;//房子内人的个数;
             addNum=function(){   //预留的增加函数人数的方法;
                 num+=1;
             }
             function query(){//这个函数就叫闭包
                 alert(num);
                 return num;//返回这个房子的人数
             }
             return query;//返回查询这个房子人数方法的指针及地址;
         }
         var res=house();//将这个房子的查询方法的指针/地址赋给变量res;
         res();//查询房子里面的人数  num=1;
         addNum();//增加房子内人的个数;
         res();//num=2
         //--所谓闭包可以这样理解:我们可以将 function比喻成 var 那么house()就相当于一个全局变量
         //num相当于house()这个全局变量的一个结构,addNum相当于一个改变house()这个全局变量部分结构的方法,
         //query()相当于house()中查询房子内部num结构的方法,因为house()相当于一个全局变量,那么它内部的
         //所以house()的结构也就相当于是全局变量。所以通过addNum()改变num值时num的变化会被保存下来,下次
         //再通过res这个指针访问house()时 num的值是已经改变后的。
     </script>
</body>
</html>

时间: 2024-08-07 00:12:08

2014-11-4的相关文章

2014.11.9心情随笔

嗯不知不觉已经夜深了,父亲与妹妹已经入睡,而我却还守着电脑看教程. 有的时候挺迷茫的,不知道自己做的这一切是为了什么,喜欢编程吗?可我说不出来喜欢它的理由,只是单纯的觉得那一行行的代码能像当初推理一样给我带来快乐,兴奋感. 可有的时候就像老师说的,我不学习不考个好的大学做这一切有什么用呢?人活着这一辈子又是为了什么呢? 是我想太多了么?同龄人该想什么?我才初二呀,有的时候挺憎恨自己为什么想那么多. 找份安稳的工作赚钱糊口养家,这已经是我的目标了,梦想什么的早就扯淡没了. 梦想离我太遥远了吗?忘了

【转载】【知识点总结】NOIP前夕 2014.11.4

2014.11.4 7:33 还有三天半就要NOIP,圈一下要背的知识点: 一.数论 1.素数判断 2.筛法求素数 3.求一个数的欧拉函数值 4.预处理欧拉函数 5.卡塔兰数递推式 6.快速幂(模素数的乘法逆元) 7.GCD 二.图论 1.最短路:①堆dijkstra ②spfa 2.kruscal 最小生成树 3.LCA(块状树) 4.匈牙利算法 5.验证二分图 6.scc缩点 7.拓扑排序 三.动态规划经典题 1.零一背包 2.完全背包 3.分组背包 4.最长上升(不下降)子序列 5.方格取

Notes of Scrum Meeting(2014/11/2)

Notes of Scrum Meeting (2014/11/2) 软件工程项目组Sevens开始项目之后的第一次Scrum Meeting报告 会议时间:2014年11月2日  20:00—20:30 与会人员:金鑫 陈少杰 雷元勇 王迪 高孟烨 邓亚梅 郑培蕾 会议地点:QQ讨论组 会议内容: 1.会议目标 项目给定的时间正式过去一周,我们开始准备的时间有些晚,所以大家在周末的任务是熟悉Android开发环境和开发语言, 为之后两周编写代码打下基础.另外就是确定今后四天的时间里大家的努力方

【知识点总结】NOIP前夕 2014.11.4

2014.11.4 7:33 还有三天半就要NOIP,圈一下要背的知识点: 一.数论 1.素数判断 2.筛法求素数 3.求一个数的欧拉函数值 4.预处理欧拉函数 5.卡塔兰数递推式 6.快速幂(模素数的乘法逆元) 7.GCD 二.图论 1.最短路:①堆dijkstra ②spfa 2.kruscal 最小生成树 3.LCA(块状树) 4.匈牙利算法 5.验证二分图 6.scc缩点 7.拓扑排序 三.动态规划经典题 1.零一背包 2.完全背包 3.分组背包 4.最长上升(不下降)子序列 5.方格取

Grml 2014.11 发布,Linux 发行版

Grml 2014.11 发布,代号为 'Gschistigschasti'.此版本提供最新的 Debian 'testing' 里面的软件包,跟往常一样,更新了硬件支持,修复了之前 Grml 版本的 bug. 新特性: new boot option getfile.retries=... - by specifying a number it controls the number of download retries for the netscript=...; grml2usb - i

虚拟化这八年-【软件和信息服务】2014.11

1998年VMware将IBM大型机应用的虚拟化技术迁移到x86平台,服务器虚拟化开始慢慢走近大众的视野.而中国人真正开始认识服务器虚拟化则始于2006年VMware开始在中国设立办事处.过去的8年是全球虚拟化大发展的八年,也是中国虚拟化奋起直追的八年. VMware于2004年初被EMC以6.25亿美金收购后,整个2004年的营业额也只有2.19亿美金,所以当时的服务器虚拟化整个市场容量还是很小的,难怪当时VMware拼命兜售才找到EMC这样一个买家,也仅仅以2003年营业额6.25倍的价格完

2014.11.27随笔。

哈哈哈哈哈哈. 有些事情,真的扯不清也说不清.我懒得去做解释,现在呢就想一心好好学习编程. 有的莫名火气大,我当初新手询问大神们教导的时候,没一个人搭理我.现在打开一些编程网站或者编程群,都是许多人在问怎么入门,有些人直接问是否有师傅带他们,如果有点闲心我兴许还反问:“如果你自学成功了,你乐意花时间带新手吗?”或者“你开口问别人之前使用百度谷歌了吗?” 11月9日到现在,我是自己自学一步步走过来的,现在才学到数组,因为对二维数组和函数的用法还有点懵,卡在这里研究几天了. 加油,争取这个星期了结数

Scrum Meeting 13 -2014.11.19

最近数据库和编译的实验课也开始了,大家晚上的时间直接被砍掉了大部分. 希望大家能顺利完成项目吧.剩下时间也不多了,如果程序还存在一些特别的问题和需要优化修改的地方也应该考虑留到下阶段进行了. Member Today’s task Next task 林豪森 与其他小组商讨整合问题 检测功能完整性,处理整合问题 宋天舒 测试项目功能实现 处理测试结果并对下阶段修改作建议 张迎春 测试项目功能实现 处理测试结果并对下阶段修改作建议 黄漠源 优化代码结构,添加注释 书写项目说明文档 黄敬博 优化代码

Scrum Meeting 11 -2014.11.17

今天和其他两个小组讨论了关于整合问题,在数据库连接等具体方面上还需要继续商讨. 我们小组内部讨论了,这周还是需要在处理整合的同时做项目整体的测试与改进的. Member Today’s task Next task 林豪森 与其他小组商讨整合问题 与其他小组商讨整合问题 宋天舒 优化代码结构,添加注释 测试项目功能实现 张迎春 修复整合存在的bug 测试项目功能实现 黄漠源 优化代码结构,添加注释 优化代码结构,添加注释 黄敬博 修复整合存在的bug 优化代码结构,添加注释 刘翔宇 优化pdf的

Scrum Meeting 9 -2014.11.15

项目开发测试要进入尾声了.大家加把劲,这周末能整合完成就最好了. 服务器方面已经能运行我们的程序了.还需要研究如何与其他两小组整合. Member Today’s task Next task 林豪森 协助测试及服务器部署 协助测试及服务器部署 宋天舒 服务器程序部署及运行测试 服务器程序部署及运行测试 张迎春 修复整合存在的bug 修复整合存在的bug 黄漠源 服务器程序部署及运行测试 服务器程序部署及运行测试 黄敬博 修复整合存在的bug 修复整合存在的bug 刘翔宇 优化pdf的信息提取问