這篇文章不是全面講閉包知識的,而是針對那些已經對閉包有所瞭解可是還存在疑惑的人羣。好比:閉包爲什麼能保存變量?接下來就詳細講述此類問題。如下內容來自犀牛書第六版。javascript
函數柯里化:java
function curry(fn){ var arg1 = Array.prototype.slice.call(arguments,1); return function(){ var arg2 = Array.prototype.slice.call(arguments); var mergeArr = arg1.concat(arg2); return fn.apply(null,mergeArr); } } function add(num1,num2){ return num1 + num2; } var curriedAdd = curry(add, 5); alert(curriedAdd(3)); // 8
外部函數中定義的局部變量在函數返回以後就不存在了,那麼嵌套的函數是如何調用不存在的做用域鏈的呢?如上面所示,調用curriedAdd()的時候,第一次傳入的5是存在的。那麼5爲何能保存在函數變量裏面的呢?閉包
閉包:函數定義時的做用域鏈到函數執行時仍然有效。app
咱們將函數做用域描述爲一個對象列表,不是綁定的棧。每次調用javascript函數的時候,都會爲之建立一個新的局部變量對象來保存局部變量,把這個對象添加至做用域鏈中。當函數返回的時候,就從做用域鏈中將這個綁定變量的對象刪除。函數
1.若是不存在嵌套的函數,也沒有其餘引用指向這個綁定的對象,它就會被當作垃圾回收掉。
2.若是定義了嵌套的函數,每一個嵌套的函數都各自對應一個做用域鏈,而且這個做用域鏈指向一個變量綁定對象。
(1)若是這些嵌套函數對象在外部函數中保存了下來(好比賦值給外部函數中的某個變量),它們也會和所指向的變量綁定對象同樣當作垃圾回收
(2)可是若是這個函數定義了嵌套函數,並將它們做爲返回值返回,或者存儲在某處的屬性裏,這時就會有一個外部引用指向這個嵌套函數,它就不會被當作垃圾回收。而且它所指向的變量綁定對象也不會被看成垃圾回收。prototype