JavaScript惰性载入函数
2013-03-03 23:14 youxin 阅读(281) 评论(0) 编辑 收藏 举报因为浏览器之间行为的差异,多数JavaScript代码包含了大量的if语句,将执行引导到正确的代码中。看看XMLHttpRequest(XHR)对象中的createXHR()函数:
function createXHR(){ if(typeofXMLHttpRequest!="undefined"){ returnnewXMLHttpRequest(); }elseif(typeofActiveXObject!="undefined"){ if(typeof arguments.callee.activeXString !="string"){ var versions =["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"]; for(var i =0, len = versions.length; i < len; i++){ try{ newActiveXObect(versions[i]); arguments.callee.activeXString = versions[i]; break; }catch(ex){ //跳过 } } } returnnewActiveXObect(arguments.callee.activeXString); }else{ thrownewError("No XHR object available."); }}
每次调用createXHR()的时候,它都要对浏览器所支持的能力仔细检查。首先检查内置的XHR,然后测试有没有基于ActiveX的XHR,最后如果没有发现的话就抛出一个错误。每次调用该函数都是这样,即使每次调用时分支的结果都不变:如果浏览器支持内置XHR,那么它就一直支持了,那么这种测试就变得没有必要了。即使只有一个if语句的代码,也肯定要比没有if语句的慢,所以如果if语句不必每次执行,那么代码可以运行的更快一些。解决方案就是称之为惰性载入的技巧。
惰性载入表示函数执行的分支仅会发生一次:即函数第一次调用的时候。在第一次调用的过程中,该函数会覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行的分支了。例如,可以用下面的方式使用惰性载入重写createXHR():
function createXHR(){ if(typeofXMLHttpRequest!="undefined"){ createXHR =function(){ returnnewXMLHttpRequest(); } }elseif(typeofActiveXObject!="undefined"){ createXHR =function(){ if(typeof arguments.callee.activeXString !="string"){ var versions =["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"]; for(var i =0, len = versions.length; i < len; i++){ try{ var xhr =newActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch(ex){ //跳过 } } } returnnewActiveXObect(arguments.callee.activeXString); } }else{ createXHR =function(){ thrownewError("No XHR object available."); }; } return createXHR();}
在这个惰性载入的createXHR()中,if语句的每一个分支都会为createXHR变量赋值,有效覆盖了原有的函数。最后一步便是调用新赋值的函数。下一次调用createXHR()的时候,就会直接调用分配的函数,这样就不用再次调用if语句了。
惰性载入函数有两个主要有点。第一,要执行的适当代码只有当实际调用函数时才进行。某些JavaScript库一开始就根据浏览器功能或者怪癖执行很多代码分支,将所有东西实先设置好。惰性载入则将这些计算尽可能的推迟,保证了恰当的功能而又不影响初始脚本的执行时间。第二,尽管第一次调用该函数会因为额外的第二个函数调用而稍微慢一点,但是所有后续的调用都会更快,因为后面避免了多重if条件。