惰性载入函数,其实就是帮助我们减少重复执行一些处理不同分支的逻辑语句,提升函数处理速度。
通常我们为了处理浏览器之间的差异,我们通常会定义一系列判断语句。例如,下面这段代码
function createXHR(){
if(typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
}else if(typeof ActiveXObject != "undefined"){
if(typeof arguments.callee.activeXString != "string"){
var version = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
for(i=0,len=version2.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.");
}
}
这个函数其实就是检查浏览器对XHR的支持能力,如果没有基于ActiveX的XHR,就会抛出一个异常。当我们创建XHR的时候都会调用一次,其实我们只需要检查一次其支不支持即可,if语句不必每次都执行。我们就可以使用惰性载入的技巧。
惰性载入表示函数的分支仅会发生一次。
我们再来看使用惰性载入重写的代码
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 version = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
for(i=0,len=version2.length;i<len;i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
}catch(ex){
//跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
}else{
createXHR = function(){ //覆盖当前函数
throw new Error("No XHR object available.");
}
}
}
我们可以看到,我们执行第一次的时候,已经将分支中的变量值覆盖了原函数,所以当我们下次调用时候,就不必再执行if语句了。如果我们想第一执行的时候就直入主题,我们可以一开始先自执行一遍函数,调用的时候就可以直接运行最终目标函数了。
但其会在代码首次加载时损耗一点性能。
var createXHR = (function(){
if(typeof XMLHttpRequest != "undefined"){
createXHR = function(){ //覆盖当前函数
return new XMLHttpRequest();
}
}else if(typeof ActiveXObject != "undefined"){
createXHR = function(){ //覆盖当前函数
if(typeof arguments.callee.activeXString != "string"){
var version = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
for(i=0,len=version2.length;i<len;i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
}catch(ex){
//跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
}else{
createXHR = function(){ //覆盖当前函数
throw new Error("No XHR object available.");
}
}
})();
这样利用匿名自执行函数就可以实现我们想要的效果。
惰性载入用法还要看具体场景,如果是不稳定的分支判断,就不太适合使用惰性载入了。