這是一篇關於使用JScript RuntimeObject (MSDN)調試的文章。雖然這些範例中的大多數在其他瀏覽器中不能運行,但在IE 5.5+中都能運作。
洩漏的全域標識符
比如說你一不小心創建了一個全域屬性,如:
function playRugby(players) {
var items,
i;
len = items.length;
// Global.
}
function kick() {
var x = 10
y = 11;
// As I makes y global.
}
當呼叫playRugby時,創建了全域屬性len,如果它尚未存在,那麼就將items.length的值賦給它。同樣,當調用kick時,創建了全域屬性y。
這些全域變數都不是故意的。它們破壞了封裝並洩漏了執行的細節。這可能會導致衝突和棘手的依賴問題。
要偵測這些不小心建立的全域標識符,我們可以使用for in迴圈全域物件。 Firebug的”DOM”標籤提供了這個實用的全域偵測。
遺憾的是,在IE中,for in不能列舉任何全域變數和函數宣告。看看下面的例子:
// Property of global variable object.
var EX1_GLOBAL_VARIABLE = 10;
// Property of global object.
this.EX1_GLOBAL_PROPERTY = 11;
// Property of global variable object.
function EX1_GLOBAL_FUNCTION(){}
(function(){
var results = [];
for(var p in this) {
results.push(p);
}
alert("Leaked:n" + results.join("n"));
})();
在IE中,結果包含一個window屬性組合和使用者定義的四個屬性之一:EX1_GLOBAL_PROPERTY 。
那麼,其它三個使用者定義的屬性發生了什麼事?為什麼它們不能在for in迴圈中顯示出來。
事實證明,枚舉全域物件時將枚舉已賦值的全域物件屬性,而不列舉全域變數。
為什麼全域屬性能枚舉而全域變數不能。經驗告訴我們,JScript 給全域變數(用var宣告)打了DontEnum標記。由於全域物件是作為全域變數物件來定義的,這看起來似乎是一個合理的解釋。這並不標準,但能解釋IE中的行為。不過,Eric Lippert 提出了另一種解釋:全域物件和全域變數物件是IE中兩個不同的物件。
根據MS-ES3:
JScript 5.x 中的變數宣告建立了全域物件的屬性,該屬性具有DontEnum 特性。