测试代码1:
function createXHR() { if(typeof XMLHttpRequest!='undfined') { return new XMLHttpRequest(); }else if(typeof ActiveXObject!='undefined') { //第一次执行的时候不是string,那么就会执行if里面的代码 if(typeof arguments.callee.activeXString!='string') { var versions=['MSXML2.XMLHttp','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp.6.0']; for(var i=0,length=versions.length;i<length;i++) { try{ var xhr=new ActiveXObject(versions[i]); arguments.callee.activeXString=versions[i]; break; }catch(e) { } } } //第二次来的时候直接构造函数!因为arguments.callee表示函数createXHR,通过给这个函数附加 //属性的方法来进行判断这个函数是否已经执行过了! return new ActiveXOject(arguments.callee.activeXString); }else { throw new Error("不支持XHR"); } } alert(createXHR());//打印XHR对象 alert(createXHR.activeXString);//如果在不执行原生的XHR的浏览器中,这里就会打印出通过IE创建的HXR的版本号,这个属性是在函数上面!note:这种构造的问题是,当下次还是在同一个浏览器中调用该方法,他还是会执行其中的if和else if语句,其实这是完全没有必要的,因为如果该浏览器支持那么它就一直支持了!所以我们的做法就是在第一次执行后把这个函数赋值为一个新的函数,那么下次调用的时候就调用这个新的函数而不用再次进行判断了!
function createXHR() { if(typeof XMLHttpRequest!='undfined') { createXHR=function() { return new XMLHttpRequest(); } }else if(typeof ActiveXObject!='undefined') { createXHR=function() { //第一次执行的时候不是string,那么就会执行if里面的代码 if(typeof arguments.callee.activeXString!='string') { var versions=['MSXML2.XMLHttp','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp.6.0']; for(var i=0,length=versions.length;i<length;i++) { try{ var xhr=new ActiveXObject(versions[i]); arguments.callee.activeXString=versions[i]; break; }catch(e) { } } } //第二次来的时候直接构造函数!因为arguments.callee表示函数createXHR,通过给这个函数附加 //属性的方法来进行判断这个函数是否已经执行过了! return new ActiveXOject(arguments.callee.activeXString); } }else { createXHR=function() { throw new Error("不支持XHR"); } } //这种通过把函数赋值为一个新的函数的形式还是有性能损失的,因为第一次调用的时候返回值会一直等到最后 //也就是所有的分支都结束的时候,但是以后调用会更快! return new createXHR(); } createXHR(); createXHR();note:这种实现 在第一次调用的时候存在惩罚,例如浏览器支持原生的XHR,那么返回该对象也会等到代码的最后!
var createXHR=(function() { if(typeof XMLHttpRequest!='undfined') { alert(1); return function() { alert(2); return new XMLHttpRequest(); } }else if(typeof ActiveXObject!='undefined') { return function() { //第一次执行的时候不是string,那么就会执行if里面的代码 if(typeof arguments.callee.activeXString!='string') { var versions=['MSXML2.XMLHttp','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp.6.0']; for(var i=0,length=versions.length;i<length;i++) { try{ var xhr=new ActiveXObject(versions[i]); arguments.callee.activeXString=versions[i]; break; }catch(e) { } } } //第二次来的时候直接构造函数!因为arguments.callee表示函数createXHR,通过给这个函数附加 //属性的方法来进行判断这个函数是否已经执行过了! return new ActiveXOject(arguments.callee.activeXString); } }else { return function() { throw new Error("不支持XHR"); } } })(); //这是通过一种自执行的匿名函数来完成的!通过自执行得到函数进而减少多次执行而导致的多余的if.else判断 //如果浏览器支持原生的XHR那么你会发现上面只会弹出一次1,其它都是2! createXHR(); createXHR(); createXHR(); createXHR();总结:
(1)通过"动态覆盖"或者"匿名函数自执行"的方式能够减少每次多余的分支判断!
(2)至于图片懒加载的原理可以阅读其它的相关知识.