當面試官問你閉包時,他究竟想聽到些什麼?
「請你講一下閉包」——這道題幾乎是前端面試必問的問題,今天我試著總結一下如何優雅的回答這道題
閉包是什麼?
閉包是有許可權訪問其他函數作用域內的變數的一個函數。
這是《JavaScript高級程序設計》中給出的定義,如果你想就用這一句話就把面試官搞定幾乎是不可能的。
因為這句話還存在下面幾個深入的問題:
為什麼其他非閉包的函數沒有許可權訪問另一個函數的內部作用域
為什麼閉包有這個許可權
什麼是函數作用域
面試官更想知道的是你是否知道上面的內容。
那好一個更周全的解釋方法應運而生:
由於在JS中,變數的作用域屬於函數作用域,在函數執行後作用域就會被清理、內存也隨之回收,但是由於閉包是建立在一個函數內部的子函數,由於其可訪問上級作用域的原因,即使上級函數執行完,作用域也不會隨之銷毀,這時的子函數——也就是閉包,便擁有了訪問上級作用域中的變數的許可權,即使上級函數執行完後作用域內的值也不會被銷毀。
稍微有些啰嗦,但是一分鐘以內應該足夠了(如果流利的話)。這樣一來,面試官基本上了解了你對於上面三個知識點是掌握的。
閉包解決了什麼?
請放心,就憑上面那段話,面試官是不會善擺干休的。他一定會繼續追問,一般來說會問——閉包解決了什麼問題。
阮一峰在他的博客——《學習Javascript閉包(Closure)》中寫到:在本質上,閉包就是將函數內部和函數外部連接起來的一座橋樑。
阮一峰寫的太文藝了,我想務實點的說法應該是下面這樣:
由於閉包可以緩存上級作用域,那麼就使得函數外部打破了「函數作用域」的束縛,可以訪問函數內部的變數。以平時使用的Ajax成功回調為例,這裡其實就是個閉包,由於上述的特性,回調就擁有了整個上級作用域的訪問和操作能力,提高了極大的便利。開發者不用去寫鉤子函數來操作上級函數作用域內部的變數了。
閉包有哪些應用場景
這個問題也極有可能被追問。
我的回答會是下面的樣子:
閉包隨處可見,一個Ajax請求的成功回調,一個事件綁定的回調方法,一個setTimeout的延時回調,或者一個函數內部返回另一個匿名函數,這些都是閉包。簡而言之,無論使用何種方式對函數類型的值進行傳遞,當函數在別處被調用時都有閉包的身影。
閉包有哪些
原理比較深奧:要想完全掌握閉包,一定要清楚函數作用域、內存回收機制、作用域繼承等,然而閉包是隨處可見的,很可能開發者在不經意間就寫出了一個閉包,理解不夠深入的話很可能造成運行結果與預期不符。
代碼難以維護:閉包內部是可以緩存上級作用域,而如果閉包又是非同步執行的話,一定要清楚上級作用域都發生了什麼,而這樣就需要對代碼的運行邏輯和JS運行機制相當了解才能弄明白究竟發生了什麼。
總結
閉包是JavaScript這門語言中非常重要但又難以掌握的概念。如果掌握了閉包並運用自如的話,會讓你「功力大增」
參考: 《JavaScript高級程序設計》 《你不知道的JavaScript》 阮一峰的網路日誌《學習Javascript閉包(Closure)》
歡迎關注我的公眾號 微信搜索——「較真的前端」
推薦閱讀:
※面試總結-語言篇(從內存底層看待c/c++)
※面試 | 如何在面試中巧妙地"偽裝"成極具團隊精神的社交達人?
※{面試禮儀} 如何應對面試官的9大疑問
※關於安全工程師崗位的面試
※19道小米網運維工程師筆試真題,你能通關嗎?