一個內存釋放的實例
CollectGarbage,是IE的一個特有屬性,用於釋放內存的
使用方法嘛應該是,將該變量或引用對象,設置為null或delete
然后在進行釋放動作
在做CollectGarbage前,要必需清楚的兩個必備條件:
========= 美麗的分割線 =========
//---------------------------------------------------------
// JavaScript對象何時失效
//---------------------------------------------------------
function testObject() {
var _obj1 = new Object();
}
function testObject2() {
var _obj2 = new Object();
return _obj2;
}
// 示例1
testObject();
// 示例2
testObject2()
// 示例3
var obj3 = testObject2();
obj3 = null;
// 示例4
var obj4 = testObject2();
var arr = [obj4];
obj3 = null;
arr = [];
在這四個示例中:
- “示例1”在函數testObject()中構造了_obj1,但是在函數退出時,
它就已經離開了函數的上下文環境,因此_obj1失效了;
- “示例2”中,testObject2()中也構造了一個對象_obj2並傳出,因
此對象有了“函數外”的上下文環境(和生存周期),然而由於函數
的返回值沒有被其它變量“持有”,因此_obj2也立即失效了;
- “示例3”中,testObject2()構造的_obj2被外部的變量obj3持用了,
這時,直到“obj3=null”這行代碼生效時,_obj2才會因為引用關系
消失而失效。
- 與示例3相同的原因,“示例4”中的_obj2會在“arr=[]”這行代碼
之后才會失效。
但是,對象的“失效”並不等會“釋放”。在JavaScript運行環境的內部,沒
有任何方式來確切地告訴用戶“對象什么時候會釋放”。這依賴於JavaScript
的內存回收機制。——這種策略與.NET中的回收機制是類同的。
在前面的Excel操作示例代碼中,對象的所有者,也就是"EXCEL.EXE"這個進程
只能在“ActiveX Object實例的釋放”之后才會發生。而文件的鎖,以及操作
系統的權限憑證是與進程相關的。因此如果對象僅是“失效”而不是“釋放”,
那么其它進程處理文件和引用操作系統的權限憑據時就會出問題。
——有些人說這是JavaScript或者COM機制的BUG。其實不是,這是OS、IE
和JavaScript之間的一種復雜關系所導致的,而非獨立的問題。
Microsoft公開了解決這種問題的策略:主動調用內存回收過程。
在(微軟的)JScript中提供了一個CollectGarbage()過程(通常簡稱GC過程),
GC過程用於清理當前IE中的“失效的對象失例”,也就是調用對象的析構過程。
在上例中調用GC過程的代碼是:
//---------------------------------------------------------
// 處理ActiveX Object時,GC過程的標准調用方式
//---------------------------------------------------------
function writeXLS() {
//(略...)
excel.Quit();
excel = null;
setTimeout(CollectGarbage, 1);
}
第一行代碼調用excel.Quit()方法來使得excel進程中止並退出,這時由於JavaScript
環境執有excel對象實例,因此excel進程並不實際中止。
第二行代碼使excel為null,以清除對象引用,從而使對象“失效”。然而由於
對象仍舊在函數上下文環境中,因此如果直接調用GC過程,對象仍然不會被清理。
第三行代碼使用setTimeout()來調用CollectGarbage函數,時間間隔設為'1',只
是使得GC過程發生在writeXLS()函數執行完之后。這樣excel對象就滿足了“能被
GC清理”的兩個條件:沒有引用和離開上下文環境。
GC過程的使用,在使用了ActiveX Object的JS環境中很有效。一些潛在的ActiveX
Object包括XML、VML、OWC(Office Web Componet)、flash,甚至包括在JS中的VBArray。
從這一點來看,ajax架構由於采用了XMLHTTP,並且同時要滿足“不切換頁面”的
特性,因此在適當的時候主動調用GC過程,會得到更好的效率用UI體驗。
事實上,即使使用GC過程,前面提到的excel問題仍然不會被完全解決。因為IE還
緩存了權限憑據。使頁的權限憑據被更新的唯一方法,只能是“切換到新的頁面”,
因此事實上在前面提到的那個SPS項目中,我采用的方法並不是GC,而是下面這一
段代碼:
//---------------------------------------------------------
// 處理ActiveX Object時采用的頁面切換代碼
//---------------------------------------------------------
function writeXLS() {
//(略...)
excel.Quit();
excel = null;
// 下面代碼用於解決IE call Excel的一個BUG, MSDN中提供的方法:
// setTimeout(CollectGarbage, 1);
// 由於不能清除(或同步)網頁的受信任狀態, 所以將導致SaveAs()等方法在
// 下次調用時無效.
location.reload();
}
========= 美麗的分割線 =========
delete 運算符在手冊上的說明
========= 美麗的分割線 =========
最后之最后,關於GC的一個補充說明:在IE窗體被最小化時,IE將會主動調用一次
CollectGarbage()函數。這使得IE窗口在最小化之后,內存占用會有明顯改善。
<SCRIPT LANGUAGE="JavaScript">
<!--
strTest = "1";
for ( var i = 0; i < 25; i ++ )
{
strTest += strTest;
}
alert(strTest);
delete strTest;
CollectGarbage();
//-->
</SCRIPT>
<!--
strTest = "1";
for ( var i = 0; i < 25; i ++ )
{
strTest += strTest;
}
alert(strTest);
delete strTest;
CollectGarbage();
//-->
</SCRIPT>
CollectGarbage,是IE的一個特有屬性,用於釋放內存的
使用方法嘛應該是,將該變量或引用對象,設置為null或delete
然后在進行釋放動作
在做CollectGarbage前,要必需清楚的兩個必備條件:
引用
- 一個對象在其生存的上下文環境之外,即會失效。
- 一個全局的對象在沒有被執用(引用)的情況下,即會失效。
- 一個全局的對象在沒有被執用(引用)的情況下,即會失效。
//---------------------------------------------------------
// JavaScript對象何時失效
//---------------------------------------------------------
function testObject() {
var _obj1 = new Object();
}
function testObject2() {
var _obj2 = new Object();
return _obj2;
}
// 示例1
testObject();
// 示例2
testObject2()
// 示例3
var obj3 = testObject2();
obj3 = null;
// 示例4
var obj4 = testObject2();
var arr = [obj4];
obj3 = null;
arr = [];
在這四個示例中:
- “示例1”在函數testObject()中構造了_obj1,但是在函數退出時,
它就已經離開了函數的上下文環境,因此_obj1失效了;
- “示例2”中,testObject2()中也構造了一個對象_obj2並傳出,因
此對象有了“函數外”的上下文環境(和生存周期),然而由於函數
的返回值沒有被其它變量“持有”,因此_obj2也立即失效了;
- “示例3”中,testObject2()構造的_obj2被外部的變量obj3持用了,
這時,直到“obj3=null”這行代碼生效時,_obj2才會因為引用關系
消失而失效。
- 與示例3相同的原因,“示例4”中的_obj2會在“arr=[]”這行代碼
之后才會失效。
但是,對象的“失效”並不等會“釋放”。在JavaScript運行環境的內部,沒
有任何方式來確切地告訴用戶“對象什么時候會釋放”。這依賴於JavaScript
的內存回收機制。——這種策略與.NET中的回收機制是類同的。
在前面的Excel操作示例代碼中,對象的所有者,也就是"EXCEL.EXE"這個進程
只能在“ActiveX Object實例的釋放”之后才會發生。而文件的鎖,以及操作
系統的權限憑證是與進程相關的。因此如果對象僅是“失效”而不是“釋放”,
那么其它進程處理文件和引用操作系統的權限憑據時就會出問題。
——有些人說這是JavaScript或者COM機制的BUG。其實不是,這是OS、IE
和JavaScript之間的一種復雜關系所導致的,而非獨立的問題。
Microsoft公開了解決這種問題的策略:主動調用內存回收過程。
在(微軟的)JScript中提供了一個CollectGarbage()過程(通常簡稱GC過程),
GC過程用於清理當前IE中的“失效的對象失例”,也就是調用對象的析構過程。
在上例中調用GC過程的代碼是:
//---------------------------------------------------------
// 處理ActiveX Object時,GC過程的標准調用方式
//---------------------------------------------------------
function writeXLS() {
//(略...)
excel.Quit();
excel = null;
setTimeout(CollectGarbage, 1);
}
第一行代碼調用excel.Quit()方法來使得excel進程中止並退出,這時由於JavaScript
環境執有excel對象實例,因此excel進程並不實際中止。
第二行代碼使excel為null,以清除對象引用,從而使對象“失效”。然而由於
對象仍舊在函數上下文環境中,因此如果直接調用GC過程,對象仍然不會被清理。
第三行代碼使用setTimeout()來調用CollectGarbage函數,時間間隔設為'1',只
是使得GC過程發生在writeXLS()函數執行完之后。這樣excel對象就滿足了“能被
GC清理”的兩個條件:沒有引用和離開上下文環境。
GC過程的使用,在使用了ActiveX Object的JS環境中很有效。一些潛在的ActiveX
Object包括XML、VML、OWC(Office Web Componet)、flash,甚至包括在JS中的VBArray。
從這一點來看,ajax架構由於采用了XMLHTTP,並且同時要滿足“不切換頁面”的
特性,因此在適當的時候主動調用GC過程,會得到更好的效率用UI體驗。
事實上,即使使用GC過程,前面提到的excel問題仍然不會被完全解決。因為IE還
緩存了權限憑據。使頁的權限憑據被更新的唯一方法,只能是“切換到新的頁面”,
因此事實上在前面提到的那個SPS項目中,我采用的方法並不是GC,而是下面這一
段代碼:
//---------------------------------------------------------
// 處理ActiveX Object時采用的頁面切換代碼
//---------------------------------------------------------
function writeXLS() {
//(略...)
excel.Quit();
excel = null;
// 下面代碼用於解決IE call Excel的一個BUG, MSDN中提供的方法:
// setTimeout(CollectGarbage, 1);
// 由於不能清除(或同步)網頁的受信任狀態, 所以將導致SaveAs()等方法在
// 下次調用時無效.
location.reload();
}
========= 美麗的分割線 =========
delete 運算符在手冊上的說明
引用
從對象中刪除一個屬性,或從數組中刪除一個元素。
delete expression
expression 參數是一個有效的 JScript 表達式,通常是一個屬性名或數組元素。
說明
如果 expression 的結果是一個對象,且在 expression 中指定的屬性存在,而該對象又不允許它被刪除,則返回 false。
在所有其他情況下,返回 true。
delete expression
expression 參數是一個有效的 JScript 表達式,通常是一個屬性名或數組元素。
說明
如果 expression 的結果是一個對象,且在 expression 中指定的屬性存在,而該對象又不允許它被刪除,則返回 false。
在所有其他情況下,返回 true。
最后之最后,關於GC的一個補充說明:在IE窗體被最小化時,IE將會主動調用一次
CollectGarbage()函數。這使得IE窗口在最小化之后,內存占用會有明顯改善。
