手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表Tag:数据库

深入理解Javascript闭包(closure)

經過指點,獲悉原文為:http://www.felixwoo.com/archives/247

我轉貼的文章來源:http://www.knowsky.com/442121.html

PS:虽然我是从上面拷来的,但我并不建议打开这个网页看,因为,上面全是广告。个人猜测,代码也是他拷来的,但没有亲自验证,我也没法打包票。不过东西有点用,所以我也就COPY过来了。

内容如下:

最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目。

一、什么是闭包?
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码:

JavaScript代码
  1. function a(){  
  2.  var i=0;  
  3.  function b(){  
  4.  alert(++i);  
  5.  }  
  6.  return b;  
  7. }  
  8. var c = a();  
  9. c();  

这段代码有两个特点:
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对象,如下图所示:(这里看了一下,确实没有图,看来果然是拷贝过来的,稍稍验证了我的说法,呵呵。。。。唉。可惜我确实不知道原文在哪里,不过,我是从他的网站拷来的,还是给他一个链接,毕竟我的资料来源是该网站)

大小: 56.19 K
尺寸: 500 x 180
浏览: 1985 次
点击打开新窗口浏览全图

(附上原文圖片)

如图所示,当在函数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执行后不会被回收的原因。

 

Tags: 闭包, closure, javascript, archive

优化递归的效率

原文来自博客园,把代码全部翻译成了PHP的,因为这些东西对PHP同样适用。

函数递归调用是很常见的做法,但是它往往是低效的,本文探讨优化递归效率的思路。
1.尾递归转换成迭代
尾递归是一种简单的递归,它可以用迭代来代替 比如 求阶乘函数的递归表达

PHP代码
  1. <?php  
  2. function  f( $n = 0)  
  3. {  
  4.     if($n<=0)return 1;  
  5.     return $n*f($n-1);  
  6. }  
  7. ?>  

可以转换成完全等价的循环迭代

PHP代码
  1. <?php  
  2. function f($n = 0)  
  3. {  
  4.     $r=0;  
  5.     while$n-- > 0)  
  6.         $r *= $n;  
  7.     return $r;  
  8. }  
  9. ?>  

尾递归是最简单的情形,好的编译器甚至可以自动的识别尾递归并把它转换成循环迭代。


更多看详细

» 阅读全文

Tags: php, 递归, 效率, 优化

apache rewrite 详解

懒得写上什么,apache的rewrite一向是最让人头疼的。这是我几年前找的文章,继续转贴一下,毕竟以前的BLOG我也不知道能够被保留多久, 这个毕竟是自己的,只要没啥意外,会一直保留着的。

收藏自:竹笋炒肉

» 阅读全文

Tags: 转贴, apache, rewrite, 解释

小家伙剃了个小光头

小家伙今天理了个小光头,不过还不算是太光,外婆不让。唉。胎毛还是留了点在头上。

上张照片。。。

图片附件(缩略图):
大小: 796.88 K
尺寸: 500 x 375
浏览: 2491 次
点击打开新窗口浏览全图

Tags: 佑阳, 光头, 照片

杂谈二

博客本来就是用来记录内心想法的东西,只是我的博客可能记录的技术类的东西相对较多,国庆期间嘛,心思也不在技术上,于是就有了杂谈。

美国众议院、参议院终于同意了救市方案,7000亿美金,听起来很恐怖,可惜股市还是下跌了,恐怕华尔街那些人就非常开心了,压力会小一点了。我在上篇杂谈里就说过,不希望会有这种事情发生,毕竟有第一次也就会有第二次。布什在促进这件事成功,是因为不想留下污点?个人认为。两个竞选者促进成功,是因为这样可以在上台后压力小一点,反正用的钱又不是我的,也不是我下令的,责任不在我身上。可惜对于美国这种物权法很看中的国家来说,民众是怎么想的?7000亿,要纳多少税?在用自己的钱救市,心里是迷惘多一点还是期盼多一点?我交出去的钱,终于派上用场了?可惜,华尔街人应该也在想,怕啥,再怎么样,还是会有人帮我的。。。

除开经济,恐怕搞技术的人这两天都在关注着GOOGLE推出的在线备份MYSQL的innodb数据库?这里提到了,这里也提到了,其实讲的都是GOOLE CODE上的内容,谁来做小白鼠?短时间内谁敢用?估计还是要过段时间了,不过,这毕竟是一个想法,以后这种类似的东西会越来越多的吧?

再说说软件,思维导图,应该算是最近一段时间比较流行的东西了,思维导图是国内人员的翻译,详细介绍如下:

什么是MindManager?
  1.  
  2. MindManager是一个创造、管理和交流思想的通用标准,其可视化的绘图软件有着直观、友好的用户界面和丰富的功能,这将帮助您有序地组织您的思维、资源和项目进程。  
  3.   
  4. MindManager也是一个易于使用的项目管理软件,能很好提高项目组的工作效率和小组成员之间的协作性。它作为一个组织资源和管理项目的方法,可从脑图的核心分枝派生出各种关联的想法和信息。  
  5. MindManager可以使讨论和计划的过程从根本上发生变化,促进实现你的思想和方案。  
  6. 在一般的传统的讨论中至少包含四个步骤:  
  7. 1、从图表或白板上获得思想  
  8. 2、转录成为很难阅读的电子版  
  9. 3、在组织信息资料的过程中不可避免的要损失某些思想的重要关系  
  10. 4、通过印刷品或者电子邮件分发资料  
  11. 时间和资源在重复的信息中被浪费了,同事们很难理解会议的结果。  
  12. 但是,MindManager软件改变了研讨过程,只通过以下两个步骤就可以在同一页中显示出每个人的观点,从而避免了不必要的重复性的工作。  
  13. 1、迅速的以可视化形式获取和组织思想,促进团队内的协作和个体积极性。  
  14. 2、能够直接分发会议记录,比以往更快的落实各种设想。  
  15. 点击“输出”(export),可以得到PDF、Word、Powerpoint、HTML和图片格式文件。  
cnbeta上面有详细介绍,上面的也是COPY而来,地址为:http://www.cnbeta.com/articles/66193.htm,除了这个软件,另外这五款软件也是不错的,值得下载使用,我没有用过,但是看名称和介绍,就知道应该是值得用用:5个最出色必须拥有的windows xp 管理插件

Tags: 杂谈, google, mysql, 股票

Records:14123