代码重构
提炼函数
避免出现超大函数,独立出来的函数有助于代码复用,独立出来的函数更容易被覆写,独立出来的函数如果拥有一个良好的命名,他本身就起到了注释的作用
//例如:
var getUserInfo=funcion(){ ajax("http://***.com/userInfo",function(data){ console.log('userId:'+data.userId); console.log('userName:'+data.userName); }); } //改写: var getUserInfo=funcion(){ ajax("http://***.com/userInfo",printDetails(data)); } function printDetails(data){ console.log('userId:'+data.userId); console.log('userName:'+data.userName); };
合并重复的条件片段
//一个页面跳转的伪代码
var page=function(currPage){ if(currPage<0){ currPage=0; jump(currPage); }else if(currPage>=totalPage){ currPage=totalPage; jump(currPage); }else{ jump(currPage); } } //改写 var page=function(currPage){ if(currPage<0){ currPage=0; }else if(currPage>=totalPage){ currPage=totalPage; } jump(currPage); }
把条件分支语句提炼成函数
var getPrice=function(price){ var date=new Date(); if(date.getMonth()>=6&&date.getMonth()<=9){ return price*0.8; } return price; }; //改写: var isSummer=function(){ var date=new Date(); return date.getMonth()>=6&&date.getMonth()<=9; }; var getPrice=function(price){ if(isSummer()){ return price*0.8; } return price; };
合理使用循环
//一个创建XHR对象的代码,为了简化,只实现IE9以下
var createXHR=function(){ var XHR; try{ XHR=new ActiceXObject('MSXML2.XMLHttp.6.0'); }catch(e){ try{ XHR=new ActiceXObject('MSXML2.XMLHttp.3.0'); }catch(e){ XHR=new ActiceXObject('MSXML2.XMLHttp'); } } return XHR; } //改写: var createXHR=function(){ var versions=['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp']; for(var i=0,version;version=versions[i++];){ try{ return new ActiceXObject(version); }catch(e){ } } }
提前让函数退出代替嵌套条件分支
//一段遵守“一个函数只有一个出口”的伪代码
var del=function(obj){ var ret; if(!obj.isReadOnly{ //不为只读的才能被删除 if(obj.isFolder){ //如果是文件夹 ret = deletFolder(obj); }else if(obj.isFile){ ret=deletFile(obj); //如果是文件 } } return ret; } var del=function(obj){ if(!obj.isReadOnly{ //不为只读的才能被删除 return; } if(obj.isFolder){ //如果是文件夹 return deletFolder(obj); } if(obj.isFile){ return deletFile(obj); //如果是文件 } }
传递对象参数代替过长的参数列表
//例:
var setUserInfo=function(id,name,age,sex,qq,phone){ console.log("id"+id); console.log("name"+name); console.log("age"+age); console.log("sex"+sex); console.log("qq"+qq); console.log("phone"+phone); } setUserInfo(1231,'nike',18,'male','35498797','13200400580'); //改写 var setUserInfo=function(data){ console.log("id"+data.id); console.log("name"+data.name); console.log("age"+data.age); console.log("sex"+data.sex); console.log("qq"+data.qq); console.log("phone"+data.phone); } setUserInfo( { id:1231, name:'nike', age:18, sex:'male', qq:'35498797', phone:'13200400580' } );
少使用三目运算符
三目运算符常被用来if-else,两者的性能是差不多的,在实际开发中,即使一段代码循环一百万次,使用三目运算符和使用if-else的时间开销是在同一级别上的,相比损失的代码可读性和可维护性,三目运算符节省的代码量也可以忽略不计,让JS文件加载更快的方法有很多,如压缩,缓存,使用CDN等。如果条件分支逻辑简单清晰,这无碍我们使用三目运算符:var global=typeof window!=="undefined"?window:this;但如果条件分支逻辑非常复杂,最好使用if-else,这样阅读更加容易,后期修改也更加容易例如:
if(!aup||!bup){ return a===doc?-1: b=doc?1: aup?-1: bup?1: sortInput? (indexOf.call(sortInput,a)-indexOf.call(sortInput,b)): 0; }
合理使用链式调用
————方法调用结束后返回对象自身
var User=function(){ this.name=null; this.id=null; }; User.prototype.setId=function(id){ this.id=id; return this; } User.prototype.setName=function(name){ this.name=name; return this; } var user=new User(); user.setName("nike").setId("132"); //或者 // var User={ id:null, name:null, setName:function(name){ this.name=name; return this; }, setId=function(id){ this.id=id; return this; } } User.setName("nike").setId("132");
使用链式调用的方式并不会造成太多阅读上的困难,也确实能省下一些字符串和中间变量,但节省下来的字符数量同样是微不足道的,链式调用带来的坏处就是在调试的时候非常不方便,如果我们知道一条链中有错误出现,必须得先把这条链拆开才能加上一些调试log或者增加断电。这样才能定位错误出现的地方。所以还是使用普通调用比较好
var user=new User(); user.setId("134"); user.setName("nike");
用return退出多重循环
var func=function(){ var flag=false; for(var i=0;i<10;i++){ for(var j=0;j<10;j++){ if(i*j>30){ flag=true; break; } } if(flag===true)break; } } var func=function(){ var flag=false; for(var i=0;i<10;i++){ for(var j=0;j<10;j++){ if(i*j>30)return; } } }
当然用return直接退出方法会带来一个问题,如果在循环之后还有一些将被执行的代码呢?如果我们提前退出了整个方法,这些代码就不会被执行
var func=function(){ var flag=false; for(var i=0;i<10;i++){ for(var j=0;j<10;j++){ if(i*j>30)return; } } console.log("....."); }
为了解决这个问题我们可以把循环后面的代码放到return 后面,如果代码较多,就应该把它们提炼成一个单独的函数:
var print=function(){ console.log("....."); } var func=function(){ var flag=false; for(var i=0;i<10;i++){ for(var j=0;j<10;j++){ if(i*j>30)return print(); } } }