- 局部變量在函數返回以後,並不一定會被立即回收,而是會等待不再被引用的時候,纔會被回收!下面局部變量i在函數test返回以後,仍然存在,因爲有m一直引用着該數組。但一旦手動將 m = null,該數組將因爲無引用被自動回收。
- function test(){
- var i = [1,2];
- return i;
- }
- var m = test();
- alert(m);//1,2
- 結合閉包:
- //代碼引用自網絡資源
- function outerFunc(){
- var privateAttr = 10;
- function innerFunc(){
- privateAttr *= 2;
- return privateAttr;
- }
- return innerFunc;
- }
- // 通過調用outerFunc函數,返回一個指向innerFunc函數的引用,
- // 這個引用被賦給變量refInnerFunc
- var refInnerFunc = outerFunc();
- // 通過 refInnerFunc 這個引用調用到 innerFunc 函數
- refInnerFunc(); // return 20 變量privateAttr可被innerFunc訪問並修改
- refInnerFunc(); // return 40
- // 調用outerFunc函數,創建了一個新的innerFunc函數的副本
- var refInnerFunc2 = outerFunc();
- refInnerFunc(); // return 20 不同副本中變量privateAttr的值是獨立的。
- js的垃圾回收機制同樣是對不再被其他對象引用的變量或方法進行回收,引用不僅可指向變量,也可指向函數,
- 在上述js代碼中,只要指向函數 innerFunc 的引用 refInnerFunc 還沒有被設爲null,那麼處在函數 innerFunc 作用域內的局部變量都不會被js垃圾回收器回收。
- 局部變量 privateAttr 被認爲處在一個安全且相對封閉的“閉包”環境中,訪問它的唯一方法是通過調用處在同一作用域下的 innerFunc 函數來進行。直到 innerFunc 函數不再被其他對象引用,其作用域內的變量和函數才能被釋放回收。
- 其他:
- JavaScript包含一個垃圾回收的小程序,這個程序能夠週期性的遍歷JavaScript環境中的所有變量的列表,並且給這些變量所引用的值做個標記。
- 如果被引用的值是對象或數組,那麼對象的屬性或者數組的元素就會被遞歸地做個標記。通過遞歸遍歷所有值的樹或者圖,垃圾回收器就能夠找到(並標記)仍舊使用的每個值。那些沒有標記的值就是無用的存儲單元。
- 當給所有正在使用的變量做完標記之後,垃圾回收器就會開始進行清除。在這個階段中,它將遍歷環境中所有值的列表,同時釋放那些沒有標記的值。
- 所以,關鍵問題是看,當前對該變量的引用計數爲多少,如果有任何引用,那即使是臨時變量也不會被立即回收的。閉包是借用了這一點。
思考:
- 在做Javascript的對象內模擬C++中的私有成員變量的時候,也可以通過這種機制。(臨時變量無法在外部訪問,但因爲有函數在引用着,因此可以被成員函數訪問)。Nice~
- 那是不是可以在對象內定義局部函數,甚至是匿名函數,然後在成員函數中引用形成閉包,這樣也可以形成私有函數的訪問。不過從功能上看就沒有那個必要了吧~