function outerFunc(){
var privateAttr = 10;
return function(){
privateAttr *= 2;
return privateAttr;
};
}
// 通過調用outerFunc函數,返回一個指向innerFunc函數的引用,
// 這個引用被賦給變數refInnerFunc
var refInnerFunc = outerFunc();
alert(refInnerFunc());
// 通過 refInnerFunc 這個引用調用到 innerFunc 函數
refInnerFunc(); // return 20 變數privateAttr可被innerFunc訪問並修改
refInnerFunc(); // return 40
// 調用outerFunc函數,建立了一個新的innerFunc函數的副本
var refInnerFunc2 = outerFunc();
refInnerFunc2(); // return 20 不同副本中變數privateAttr的值是獨立的。
當一個javascript函數返回時,js解析器會保留它範圍內的所有變數和函數。
閉包(Closure)這個詞形象地描述了函數範圍現場被“封閉包存”起來這一行為。
直到該函數不再被其他對象引用,其範圍內的變數和函數才能被釋放回收。
按照java回收機制的解釋,方法內的局部變數在該方法被執行完畢後,
如果不再被其他對象引用,記憶體回收行程可自行選擇適當的時機回收這些局部變數。
但js的記憶體回收機制和java不同,上述js代碼的執行結果便可以證明這一點。
js的記憶體回收機制同樣是對不再被其他對象引用的變數或方法進行回收,
但因為js的引用不僅可指向變數,也可指向函數,在上述js代碼中,
只要指向函數 innerFunc 的引用 refInnerFunc 還沒有被設為null,
那麼處在函數 innerFunc 範圍內的局部變數都不會被js記憶體回收行程回收。
局部變數 privateAttr 被認為處在一個安全且相對封閉的“閉包”環境中,
訪問它的唯一方法是通過調用處在同一範圍下的 innerFunc 函數來進行。
直到 innerFunc 函數不再被其他對象引用,其範圍內的變數和函數才能被釋放回收。