我在jCT的说明中提到,jCT为了保障速度,没有用正则。今天我特意改写了以正则解析模板代码,仅仅支持注释文法jCT3版本,测试一下Build过程(也就是主要的解析过程了)的速度差异。结果如下(数值为同样循环条件下所用时间,越小越好)
(AMD双核)
FireFox 3.0.1:
非正则版本: 75
正则版本: 300
IE 8:
非正则版本:140
正则版本: 470
Chrome :
非正则版本:140
正则版本: 470
下面是在另一台机器上(AMD单核),看相对值就行了
FireFox 3.0.1:
非正则版本:150
正则版本: 350
IE6 :
速度不稳定,比IE7慢,就不贴了
IE7 :
非正则版本:200
正则版本: 578
Chrome :
非正则版本:160
正则版本: 520
Safari 3.1:
非正则版本:110
正则版本: 422
Opera 9.52:
非正则版本:109
正则版本: 650
结果很明显呀,正则版本就是慢呀,同时贴出正则的版本,(此版本中增加了一个成员属性定义,非正则版本稍后更新)
并且我没有发现Chrome在字符串处理上的优势呀
jCT 第3版 正则注释风格版源码
/** * JavaScript Common Templates(jCT) 3(第3版) 正则注释风格版 * http://code.google.com/p/jsct/ * * licensed under the MIT license. * http://www.opensource.org/licenses/mit-license.php * * Author achun (achun.shx at gmail.com) * Create Date: 2008-9-9 * Last Date: 2008-9-9 * Revision:rc3.8.9.9 */ function jCT(txt,path){//构建jCT对象,仅仅准备基础数据 this.Fn = new arguments.callee.Instance({txt:txt,path:path}); for (var i in this) this.Fn.Reserve+=','+i+','; } jCT.prototype={ Extend:function(jct){//扩展自己 for (var i in jct){ if(this[i] && this[i].Fn && this[i].Fn.JavaScriptCommonTemplates && this[i].Extend ) this[i].Extend(jct[i]); else if(this.Fn.Reserve.indexOf(','+i+',')==-1)//防止保留成员被覆盖 this[i]=jct[i]; } if(typeof jct.RunNow=='function') jct.RunNow.call(this); return this; }, ExecChilds:function(childs,exec){//执行childs对象所列成员里的某个方法,默认是Exec方法 exec=exec||'Exec'; for(var c in childs) if(this[c] && (typeof this[c][exec]=='function')) this[c][exec](childs[c]); return this; }, BuildChilds:function(childs){//构建子jCT对象,并执行RunNow if(undefined==childs) childs=[]; var cs={}; for(var i=0;i<childs.length;i++) cs[childs[i]]=true; for (var i in this) if(this[i].Fn && this[i].Fn.JavaScriptCommonTemplates && (childs.length==0 || cs[i])){ this[i].Build(); if(typeof this[i].RunNow=='function') this[i].RunNow(); } return this; }, GetView:function(){return 'Invalid templates';},//得到装配数据后的视图,此方法会在Build的过程中重建 Build:function(){//构建实例 this.Fn.Build(this); return this; } }; jCT.Instance=function(Options){ this.Src=Options.txt||''; this.Src=this.Src.replace(this.RegClear,''); this.Path=Options.path||''; this.A=[];//由src转换的模板数组 this.V=[];//GetView执行的文本结果,以数组形式存放 this.EXEC=[];//生成的js代码的临时数组 }; jCT.Instance.prototype={ JavaScriptCommonTemplates:3.0, Reserve:'',//保留成员 RegClear:/<!--clear([\w\W]*?)\/clear-->/g, RegTrim:/^\s+|\s+$/g, RegFun:/\/\*((?:(?!\*\/).)+)\*\//, Reg:/(<!---|\+-)([\w\W]*?)(-->|-\+)/g,//comment风格的定义 Build:function(self){ this.Pos=0; this.EXEC=['this.Fn.V=[];']; var ins=this; try{ this.Src.replace(this.Reg,function(all,begin,code,end,pos){ return ins.Parse(all,begin,code,end,pos,self); }); this.Push(this.Src.length,'return this.Fn.V.join("");');//最后一段 self.GetView=new Function(this.EXEC.join('\n')); }catch (ex){ this.V=['jCT Parse Error']; self.ERROR={message:ex.message + '\n'+ (ex.lineNumber || ex.number)}; } if(self.RunNow) self.RunNow(); }, Push:function(pos,code,exp){ if(pos<this.Pos) return; var htm=this.Src.slice(this.Pos,pos).replace(this.RegTrim,''); code=code.replace(this.RegTrim,''); if(htm){ this.EXEC.push('this.Fn.V.push(this.Fn.A['+this.A.length+']);'); this.A.push(htm); } if(code) if(exp) this.EXEC.push('this.Fn.V.push('+code+');'); else this.EXEC.push(code); }, Parse:function(all,begin,code,end,pos,self){ if(pos<this.Pos || this.Pos<0) return all; var ins=this; if(begin=='+-')//取值表达式+-???-+ this.Push(pos,code,true); else{//语法块<!---???--> var copy=code; copy.replace(this.RegFun,function(text,fun,at){//成员语法/*???*/ ins.Push(pos,''); ins.Pos=pos+all.length; if(fun.slice(0,1)!='+'){//jCT成员语法开始+??? code=''; return ''; } switch(fun.slice(1,2)){ case '@'://子模板开始 var name='<!---/*-'+fun.slice(1)+'*/-->'; ins.Pos=ins.Src.indexOf(name,pos+code.length); if(ins.Pos>0){ self[fun.slice(2)]=new jCT(ins.Src.slice(pos+all.length,ins.Pos),ins.Path); ins.Pos+=name.length; } break; case '$'://成员对象 var val=code.slice(at+text.length).replace(ins.RegTrim,''); var obj=new Function('return '+val+';'); self[fun.slice(2)]=obj.call(self); break; default://成员函数 self[fun.slice(1)]=new Function(code.slice(at+text.length)); break; } code=''; return ''; }); if(code) this.Push(pos,code);//普通javascript语句 } if(this.Pos>=0 && code) this.Pos=pos+all.length; return all; } };