閉包的官方的解釋是:一個擁有許多變量和綁定了這些變量的環境的表達式(一般是一個函數),於是這些變量也是該表達式的一部分。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