閉包是函數和函數的詞法環境的引用的組合 [MDN]
閉包是指有權訪問另外一個函數做用域中的變量的函數 [JS高級程序設計]
閉包是內部函數引用外部函數的變量的集合 [李兵]
閉包是一個綁定了執行環境的函數 [程劭非]
欲懂閉包,必先知道做用域、做用域鏈的含義。那麼咱們就從做用域開始講起。html
函數執行時會造成調用棧,調用函數時其執行上下文(其中保存了:變量環境和詞法環境)入棧,執行完畢出棧。執行上下文存儲着函數中聲明的變量,函數執行也會訪問其餘函數中聲明的變量。在函數執行查找變量時,變量的可見範圍就是做用域,查找變量的鏈路就變量的做用域鏈。
查找變量時遵循兩個規則:第1,函數嵌套時內部函數總能訪問外部函數中聲明的變量;第2,調用棧中的函數,老是先在自身的執行上下文找變量,再到最外層的全局執行上下文去找。數組
定義: 持有着其它做用域中變量的函數 及其持有的其它變量的集合 的組合。
產生閉包以後,變量的查找鏈路就會發生變化。首先在自身的執行上下文找變量,再到閉包中去找,最後再到最外層的全局執行上下文去找。
(1)函數的返回值是函數
(2)函數做爲參數傳遞給另外的函數閉包
回調函數都是閉包,由於函數被當作參數傳遞了
根據上述第2點,閉包的特徵仍是比較明顯的。本節介紹閉包的具體應用場景。
(1)全部使用到回調函數的地方都是閉包的應用,如事件監聽回調、Promise綁定的then回調、數組的map()函數;
(2)利用閉包模仿塊級做用域、封裝私有變量、延長局部變量的壽命;
(3)閉包和setTimeOut()結合實現防抖、節流;
(4)函數柯里化:多參數函數轉化成單參函數,好處是能夠進行參數複用。函數
// 普通的add函數 function add(x, y) { return x + y } // Currying後 function curryingAdd(x) { return function (y) { return x + y } } add(1, 2) // 普通函數調用3 curryingAdd(1)(2) // 柯里化函數調用3
閉包會攜帶包含其它函數的做用域,所以會比其餘函數佔用更多的內存,容易致使內存泄漏。若是閉包會一直使用,那麼它能夠做爲全局變量而存在;但若是使用頻率不高,並且佔用內存又比較大的話,那就儘可能讓它成爲一個局部變量。post
本文以變量的查找做爲出發點,引出了變量做用域、做用域鏈、函數的調用棧等概念。而後介紹了閉包的組成、造成過程。閉包聽起來玄妙,用起來簡單。文中還總結了閉包的典型特徵,有助於咱們在實際的開發過程當中發現閉包、理解閉包。最後,還介紹了閉包的具體使用場景,也給出了其缺點、使用注意事項。設計
參考:
https://juejin.cn/post/694469...
https://www.cnblogs.com/gg-qq...
https://time.geekbang.org/col...code