都說閉包是javaScript中一個近乎神話的概念乡革,我剛好碰到這個神話泣刹,想著怎么把它講成一個故事煌抒!javaScript中閉包無處不在的,我們要做的是識別和擁抱它装悲。
閉包到底是什么昏鹃?
當函數可以記住并訪問所在的詞法作用域(不論函數是否在當前的詞法作用域內執(zhí)行),就產生了閉包诀诊。當然洞渤,這是官話,學術語氣太強了理解起來很難受属瓣,所以我用自己的理解+接地氣的語言來詮釋一下這句話载迄,我覺得在此同時,我們可以將閉包的缺陷一起了解一下抡蛙。下面我們來看兩段代碼:
這里的兩段代碼執(zhí)行的都是將原有的a變量重新賦值并打印出來护昧,我們先來看(當函數可以記住并訪問所在的詞法作用域(不論函數是否在當前的詞法作用域內執(zhí)行),就產生了閉包)這句話怎么理解溜畅,看圖2。
首先要明白极祸,產生閉包的先決條件是函數的嵌套使用慈格!
其次再來理解概念:函數 wn() 包含在 foo() 的內部,它的詞法作用域能訪問到 foo() 的內部作用域遥金,我們將 wn() 對象本身作為返回值返回給 foo()浴捆,foo() 執(zhí)行后,其返回值(也就是內部的 wn() 函數)賦值給了psc稿械,并調用執(zhí)行了 psc() ,實際上只是通過不同的標識符引用选泻,來調用了內部函數 wn()。到這里這些文字應該都比較好理解對吧!R趁小L莶丁!好的睜大眼睛看下面這句話很重要:函數 foo() 并不是自執(zhí)行函數窝撵,圖2代碼的執(zhí)行順序并不是從上往下依次執(zhí)行的這個也能理解的吧傀顾?!代碼是執(zhí)行到最后的 psc() 調用的時候才返回去找 psc 是什么碌奉,好的找到了 psc 是函數 foo() 的賦值短曾,然后再去找 foo() 是什么,找到 foo() 這個函數的時候才依次從上向下執(zhí)行內部的代碼赐劣。剛剛我們就分析過了嫉拐,圖2的代碼其實際上只是通過不同的標識符引用最終調用的是 wn() 函數,在這個過程中魁兼,wn() 即實現了調用輸出婉徘,而它的詞法作用域又保存完成整——這就是閉包的概念。
無論通過何種手段將內部函數(這里指的是 wn() )傳遞到所在的詞法作用域以外璃赡,它都會持有對原始定義的作用域的引用判哥,無論在何處執(zhí)行這個函數,都涉及到使用閉包這一概念碉考。
——另外塌计,圖1放上來的作用一直沒說,其作用就是用來對比圖2,3侯谁。瀏覽器的引擎有垃圾回收機制(想要了解原理的自行去谷歌)锌仅。圖1中當foo() 調用完成,該函數內部將全局變量 a 賦值成了 2墙贱,當我們可以拿到這個為 2 的 a 來用時热芹,事實上,這個 foo() 函數已經功成名就惨撇,這個時候伊脓,雖然代碼還是在我們寫的js文件中,但是對于瀏覽器來說魁衙,這個已經執(zhí)行過的 foo() 函數宣布退隱江湖报腔,也不再給它分配作用域空間了,foo() 的內容也不再被使用了剖淀,引擎默認這樣做的意義是釋放瀏覽器不再使用的內存空間纯蛾,這相當于是引擎的自動優(yōu)化功能。而?閉包纵隔,這個東西翻诉,一旦形成卻是能阻止引擎的這一默認事件的發(fā)生炮姨,因為閉包形成了自己穩(wěn)定完整的內部作用域,引擎已經拿它沒有辦法了(打不過碰煌,動不了它舒岸,這個還是跟引擎的工作原理有關系),這個穩(wěn)定的內部作用域將永久的提供給? wn() 函數使用拄查,所以拜 wn() 所聲明的位置所賜吁津,它將永久擁有并在任何時間使用這個涵蓋 foo() 內部的作用域《榉觯——這就是閉包的缺點碍脏,不能釋放不需要使用的作用域,如果一個項目中這樣的閉包使用很多的話稍算,對瀏覽器性能的消耗將大大提升典尾。emmmmmmmmmm
不知道這樣講的夠不夠清楚,還不夠通俗的話我emmmm.....絞盡奶汁再想想怎么解釋糊探?