因為瀏覽器之間行為的差異,多數(shù)JavaScript 代碼包含了大量的if 語句窒朋,將執(zhí)行引導(dǎo)到正確的代碼中争拐∫钢啵看看下面來自上一章的createXHR()函數(shù)。
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined"){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i,len;
for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//跳過
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object available.");
}
}
每次調(diào)用createXHR()的時候,它都要對瀏覽器所支持的能力仔細(xì)檢查隘冲。首先檢查內(nèi)置的XHR金赦,然后測試有沒有基于ActiveX 的XHR,最后如果都沒有發(fā)現(xiàn)的話就拋出一個錯誤对嚼。每次調(diào)用該函數(shù)都是這樣夹抗,即使每次調(diào)用時分支的結(jié)果都不變:如果瀏覽器支持內(nèi)置XHR,那么它就一直支持了纵竖,那么這種測試就變得沒必要了漠烧。即使只有一個if 語句的代碼,也肯定要比沒有if 語句的慢靡砌,所以如果if 語句不必每次執(zhí)行已脓,那么代碼可以運行地更快一些。解決方案就是稱之為惰性載入的技巧通殃。
惰性載入表示函數(shù)執(zhí)行的分支僅會發(fā)生一次度液。有兩種實現(xiàn)惰性載入的方式,第一種就是在函數(shù)被調(diào)用時再處理函數(shù)画舌。在第一次調(diào)用的過程中堕担,該函數(shù)會被覆蓋為另外一個按合適方式執(zhí)行的函數(shù),這樣任何對原函數(shù)的調(diào)用都不用再經(jīng)過執(zhí)行的分支了曲聂。例如霹购,可以用下面的方式使用惰性載入重寫
createXHR()。
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
createXHR = function(){
return new XMLHttpRequest();
};
} else if (typeof ActiveXObject != "undefined"){
createXHR = function(){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len;
for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
} else {
createXHR = function(){
throw new Error("No XHR object available.");
};
}
return createXHR();
}
在這個惰性載入的createXHR()中朋腋,if 語句的每一個分支都會為createXHR 變量賦值齐疙,有效覆
蓋了原有的函數(shù)。最后一步便是調(diào)用新賦的函數(shù)旭咽。下一次調(diào)用createXHR()的時候贞奋,就會直接調(diào)用被分配的函數(shù),這樣就不用再次執(zhí)行if 語句了穷绵。第二種實現(xiàn)惰性載入的方式是在聲明函數(shù)時就指定適當(dāng)?shù)暮瘮?shù)轿塔。這樣,第一次調(diào)用函數(shù)時就不會損失性能了请垛,而在代碼首次加載時會損失一點性能催训。以下就是按照這一思路重寫前面例子的結(jié)果。
var createXHR = (function(){
if (typeof XMLHttpRequest != "undefined"){
return function(){
return new XMLHttpRequest();
};
} else if (typeof ActiveXObject != "undefined"){
return function(){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len;
for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
} else {
return function(){
throw new Error("No XHR object available.");
};
}
})();
這個例子中使用的技巧是創(chuàng)建一個匿名宗收、自執(zhí)行的函數(shù)漫拭,用以確定應(yīng)該使用哪一個函數(shù)實現(xiàn)實際的邏輯都一樣。不一樣的地方就是第一行代碼(使用var 定義函數(shù))混稽、新增了自執(zhí)行的匿名函數(shù)采驻,另外每個分支都返回正確的函數(shù)定義审胚,以便立即將其賦值給createXHR()。
惰性載入函數(shù)的優(yōu)點是只在執(zhí)行分支代碼時犧牲一點兒性能礼旅。至于哪種方式更合適膳叨,就要看的具體需求而定了。不過這兩種方式都能避免執(zhí)行不必要的代碼痘系。