關於閉包的定義衆說紛紜,下面是一些權威給出的說法:閉包
高程3:「閉包是指有權訪問另外一個函數做用域中的變量的函數」;函數
犀牛書:「函數對象能夠經過做用域鏈相互關聯起來,函數體內部的變量均可以保存在函數做用域內,這種特性在計算機科學文獻中稱爲‘閉包’」;spa
你不知道的JavaScript(上卷):「當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,即便函數是在當前詞法做用域以外執行」。code
而我對於閉包通俗直白的我的理解是:函數定義的做用域鏈在函數執行後不會消失,而是由內部函數持有對這個函數的做用域的引用,這個引用就叫做閉包。對象
能夠看出,閉包徹底是跟「(詞法)做用域」想關聯,做用域以前已作過大體介紹,以後將會再次深刻討論(詞法)做用域。blog
var variable = "window say hello"; function localFun(){ var variable = "localFun say hello"; function f(){ return variable ; } return f; } localFun()();
這裏調用 localFun() 會返回 "localFun say hello",相信你們都已經猜到了,可是爲何會返回這個結果呢?我是這樣理解的:這裏f()是localFun()的嵌套函數,它持有對localFun()內部做用域的引用(而這個引用就叫作閉包),這個引用捕捉到了局部變量,並一直保存了下來,因此返回的是"localFun say hello"。ip
可是可能有人會以爲外部函數中定義的局部變量在函數返回後就不存在了,因此localFun()的返回值應該是"window say hello"。但現實並不是如此,在js中,每次調用函數的時候,都會爲之建立一個對象保存局部變量,把這個對象添加到做用域鏈中。當函數返回的時候,若是沒有嵌套的函數,也沒有其餘引用指向這個綁定對象的時候,它纔會被看成垃圾回收掉;而若是函數定義了嵌套的函數,並將它做爲返回值返回或者存儲在某處的屬性裏,這時就會有一個外部引用指向這個嵌套的函數,他就不會被當作垃圾回收。作用域
總結:不管經過何種手段將內部函數傳遞到所在的詞法做用域之外,它都會持有對原始定義做用域的引用,不管在何處執行這個函數都會使用閉包。io