什麼是閉包?阮一峰老師說的很清楚了,定義在一個函數內部的函數,在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。 首先要瞭解Javascript的變數作用域:全局變數和局部變數。全局嘛,就是共用,任何一個函數內部可以直接讀取全局變數;局部嘛,就是私有,不暴露在外的。如何判斷該變數是全局還是局 ...
什麼是閉包?阮一峰老師說的很清楚了,定義在一個函數內部的函數,在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。
首先要瞭解Javascript的變數作用域:全局變數和局部變數。全局嘛,就是共用,任何一個函數內部可以直接讀取全局變數;局部嘛,就是私有,不暴露在外的。如何判斷該變數是全局還是局部,函數內部看它有沒有var進行聲明。沒有var聲明的變數,實際是個全局變數,別被騙咯!
傲嬌的小眼神(別被騙咯)
Javascript語言特有的"鏈式作用域"結構(chain scope),子對象會一級一級地向上尋找所有父對象的變數。所以,父對象的所有變數,對子對象都是可見的,反之則不成立。既然子對象可以讀取父對象的變數,那我們想獲取一個對象(假設為f1)裡面的變數,給f1創建一個子對象(假設為f2),並將子對象return出去,不就可以在外部訪問到這個對象(f1)的私有變數。f2就是閉包,沒錯,它就是閉包。不多說,代碼如圖:
f2即為閉包
那麼問題來了,你說閉包是為了獲取一個函數內部的私有數據而創建的,那我直接將一個想要獲取的數據return出去,外部不一樣可以獲取嘛,不多說,看權威的jquery源碼:
我非要return
外部訪問數據
也有人說閉包可以防止全局變數污染,什麼是全局變數污染?當多人一起開發一個大型項目的時候,每個人負責一塊,其中定義的全局變數可能會存在命名衝突,當項目進行整合的時候起衝突的全局變數會被覆蓋,這應該很好理解。閉包的應用將變數私有化,可以起到防止變數全局污染的作用,外部同時也可以訪問到私有化的變數。解決全局變數污染的問題,可以結合js模塊化開發思維,如下圖:
js模塊化一
js模塊化二(閉包)
兩者的區別在圖片中已經闡明瞭,可以自行試一試。閉包還有一個比較大的用處,相信你們都知道,讓這些變數的值始終保持在記憶體中。所以註意的一點就是:由於閉包會使得函數中的變數都被保存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致記憶體泄露。解決方法是,在退出函數之前,將不使用的局部變數全部刪除。(阮一峰老師原話,偷點懶0.0)。
這句話不知道你們能否瞭解,我簡單闡述下我的想法,一定要認真看完哈!首先全局變數和局部變數生命周期是不同的,全局變數存放在一個區域內,具有全局作用域;局部變數放在堆棧中,由編譯器自動分配釋放,存放函數的參數值,局部變數的值等,只有局部作用域,在程式運行期間不是一直存在,而是只在函數執行期間存在,函數的一次調用執行結束後,變數被撤銷,其所占用的記憶體也被收回(GC)。垃圾回收機制(GC)原理:垃圾收集器會按照固定的時間間隔,周期性找出不再使用的變數,然後釋放其占用的記憶體。不再使用的變數也就是生命周期結束的變數,是局部變數,局部變數只在函數的執行過程中存在,當函數運行結束,沒有其他引用(閉包),那麼該變數會被標記回收。全局變數的生命周期直至瀏覽器卸載頁面才會結束,也就是說全局變數不會被當成垃圾回收。當一個局部變數存在引用(閉包),該變數也不會被當成垃圾回收,始終存在於記憶體中。
閉包這種將變數始終存儲,大家知道有什麼好處麽?可以仔細研究想想,再深剖會發現,閉包在性能優化方面優勢很明顯,對比下return,如圖所示:
閉包與return對比
如上代碼,通過閉包,在外部對數據進行操作時候,紅框內代碼不會再一次執行,也就是f1裡面劈里啪啦一頓猛如虎的操作之後獲得的n,存儲到記憶體中後,外部操作實際上是對存儲在記憶體上的數據進行了操作。相比return,如果外部想獲得內部的私有數據再操作,那內部的程式在外部每獲取一次就需要跑一次,這無形中消耗著電腦的性能,所以我覺得,閉包的合理使用,是可以降低電腦性能的消耗起到一定的優化性能的作用。不合理的使用閉包會導致記憶體泄漏。
好了,謝謝你這麼帥,還能看完我的分享,希望對你有所幫助(辛辛苦苦寫了那麼多,兄dei,點個贊再走吧),送你一朵❀。