闭包的官方的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(一般是一个函数),于是这些变量也是该表达式的一部分。javascript
通俗点的说法是:html
从理论角度:全部的函数。由于它们都在建立的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,由于函数中访问全局变量就至关因而在访问自由变量,这个时候使用最外层的做用域。java
从实践角度:如下函数才算是闭包:git
即便建立它的上下文已经销毁,它仍然存在(好比,内部函数从父函数中返回)function testFreedom() { var freedomVar = 1; function inner(param) { echo(pclosure1, param + freedomVar);//将结果打印到pclosure1中 } return inner; }
对于inner函数来讲,freedomVar就属于自由变量。github
<p id="closure1" style="color:red"></p>
function echo(p, html) { p.innerHTML += html + '<br/>'; } function closure() { var innerVar = 0; function inner() { return ++innerVar; } return inner; } var quote = closure(); echo(pclosure1, quote());//1 echo(pclosure1, quote());//2
先看看结果状况:web
一、第一次quote函数的结果为1,第二次为2shell
二、inner嵌套在函数closure内部;函数closure返回函数inner编程
三、结合上面的闭包实践角度特色,能够得出closure是一个闭包浏览器
四、函数closure在返回后不会被GC回收,缘由以下:闭包
closure返回函数inner的引用给quote
函数inner的做用域链包含了对函数closure的活动对象(activation_1)的引用,以下图所示。
inner能够访问到closure中定义的全部变量和函数
函数inner被quote引用
1) 初始化Global Object即window对象,Variable Object(全局执行环境中的可变对象)为window对象自己。建立Scope Chain对象,假设为scope_1,其中只包含window对象
2) 扫描JavaScript源代码,从结果中能够获得定义的变量名、函数对象。按照扫描顺序:
发现函数closure的定义,使用这个定义建立函数对象,传给建立过程的Scope Chain为scope_1。将结果添加到window的属性中,名字为closure,值为返回的函数对象
3) 执行函数closure,获得返回值:
3.1 建立Activation Object,假设为activation_1;建立一个新的Scope Chain,假设为scope_2,scope_2中第一个对象为activation_1,第二个对象为window对象
3.2 处理参数列表。建立arguments对象并进行设置,将arguments设置为activation_1的属性
3.3 对closure的函数体执行相似步骤2的处理过程:
发现变量innerVar,在activation_1对象上添加innerVar属性,值为undefined
3.4 执行innerVar赋值语句,赋值为"0"
3.5 执行inner:
建立Activation Object,假设为activation_2;建立一个新的Scope Chain,假设为scope_3,scope_3中第一个对象为activation_2,接下来的对象依次为activation_一、window 对象(取自fn2的[[Scope]],即scope_2)
处理参数列表。由于inner没有参数,因此只用建立arguments对象并设置为activation_2的属性
对inner的函数体执行相似步骤2的处理过程,没有发现变量定义和函数声明
执行函数体。对任何一个变量引用,从scope_3上进行搜索,这个示例中,innerVar将在activation_1上找到
返回inner的返回值
3.6 返回结果
4) 打印结果
demo下载:
http://download.csdn.net/download/loneleaf1/8019865
参考资料:
http://www.nowamagic.net/librarys/veda/detail/1707 JavaScript闭包其一:闭包概论
http://www.nowamagic.net/librarys/veda/detail/1708 JavaScript闭包其二:闭包的实现
http://www.nowamagic.net/librarys/veda/detail/1709 JavaScript闭包其三:闭包的用法
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html 简单易懂的JavaScript闭解
http://page.renren.com/601017893/note/801095804 Javascript 闭包
http://kb.cnblogs.com/page/110782/ Javascript闭包——懂不懂由你,反正我是懂了
http://coolshell.cn/articles/6731.html 理解Javascript的闭包
http://kb.cnblogs.com/page/105708/ 深刻理解Javascript闭包(closure)
http://www.zhihu.com/question/20032419 动态做用域和词法域的区别是什么?
http://kangax.github.io/compat-table/es5/ ECMAScript5浏览器兼容表
http://www.nowamagic.net/librarys/veda/detail/1579 咱们应该如何去了解JavaScript引擎的工做原理
http://www.ibm.com/developerworks/cn/web/1006_qiujt_jsfunctional/ JavaScript 中的函数式编程实践
http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html 理解Javascript_13_执行模型详解
出处:http://www.cnblogs.com/strick/p/3997898.html