这是《 javaScript设想情势与开辟实践 》一书的末了一章”代码重构”。
以下的一些要领不是必需严格恪守的规范,遴选实践哪些,以及怎样完成这都需依据状况而定(是不是是有充足时刻)
提炼函数
假如在函数中有一段代码能够自力出来,那末最好把这些代码放进别的一个自力的函数当中去。优点有:
防止涌现超大型函数。
自力出来的函数有助于代码复用。
自力出来的函数越发轻易被改写,削减保护本钱。
自力出来的函数假如有一个优越的定名,自身就起到了解释的作用。
比方一个猎取用户信息的函数,我们还须要打印用户信息,这类状况下就能够自力出打印信息的代码。
var getUserInfo = function() {
ajax('http://xxx/userInfo', function(data) {
console.log('userId: ' + data.userId);
console.log('userName: ' + data.userName);
console.log('nickName: ' + data.nickName);
});
};
改写:
var getUserInfo = function() {
ajax('http://xxx/userInfo', function(data) {
printUserInfo(data);
});
};
var printUserInfo = function(data) {
console.log('userId: ' + data.userId);
console.log('userName: ' + data.userName);
console.log('nickName: ' + data.nickName);
};
兼并反复代码片断
假如一个函数内有一些前提语句,而前提语句内漫衍了一些反复代码,就有必要举行兼并去重事情。
比方一个分页函数paging
,函数接收一个currpage
示意应战页码,在跳转前须要推断currpage
是不是在有用的取值局限。
var paging = function(currpage) {
if (currpage <= 0) {
currpage = 0;
jump(currpage); // 跳转
} else if (currpage >= totalPage) { // 总页数totalPage
currpage = totalPage;
jump(currpage); // 跳转
} else {
jump(currpage); // 跳转
}
}
担任跳转的jump(currpage)
在每一个前提分支都涌现了,所以完整把这句代码自力出来:
var paging = function(currpage) {
if (currpage <= 0) {
currpage = 0;
} else if (currpage >= totalPage) { // 总页数totalPage
currpage = totalPage;
}
jump(currpage); // 跳转
}
把前提语句提炼成函数
在递次设想中,庞杂的前提语句是致使递次难以浏览和明白的重要原因,而且轻易增大函数代码量。比方以一个盘算商品价格的getPrice
函数,商品盘算有个划定规矩,炎天商品以8折出卖。
var getPrice = function(price) {
var date = new Date;
if (date.getMonth() >= 6 && date.getMonth() <= 9 ) { // 处于炎天
return price * 0.8
}
return price;
}
个中的前提语句if (date.getMonth() >= 6 && date.getMonth() <= 9 )
假如改写提炼成一个自力的函数,既能更正确的表达代码的意义,函数名又能起到解释作用。
var isSummer = function() {
var dateMonth = (new Date).getMonth();
return dateMonth >= 6 && dateMonth <= 9 ;
};
var getPrice = function(price) {
var date = new Date;
if ( isSummer() ) { // 处于炎天
return price * 0.8
}
return price;
};
合理运用轮回
在函数体内,假如有些代码是担任一些反复性的事情,那末合理运用轮回不仅能够完成一样的功用,还能够使代码量更少,有一段建立XHR对象的代码,为了简化代码,只检测IE9已下的浏览器。
var creatXHR = function() {
var xhr;
try{
xhr = new ActiveXObject('MSXML2.XMLHTTP.6.0');
} catch(e) {
try{
xhr = new ActiveXObject('MSXML2.XMLHTTP.3.0');
} catch(e) {
xhr = new ActiveXObject('MSXML2.XMLHTTP');
}
}
return xhr;
};
var xhr = creatXHR();
下面天真的运用轮回,能够获得上面代码一样的结果:
var creatXHR = function() {
var versions = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for (var i = 0;i < versions.length; i++) {
try{
return new ActiveObject( version[i] );
}catch(e) {
}
}
};
var xhr = creatXHR();
提早让函数退出嵌套前提分支
初学者能够有如许一个意见:”每一个函数只能有一个进口和一个出口。”当代编程言语都邑限定函数有一个进口。然则关于”函数只要一个出口”,每每有不一样的意见。
下面是一个恪守“函数只要一个出口”的代码。
var del = fucntion(obj) {
var ret;
if (!obj.isReadOnly) { // 不为只读才删除
if (obj.isFolder) { // 推断文件夹
ret = deletFolder(obj);
} else if (obj.isFile) { // 推断文件
ret = deletFile(obj);
}
}
return ret;
}
嵌套的前提分支语句是代码保护者的恶梦,假如对函数的盈余部份不感兴趣,那就应当马上退出。
我们能够遴选一些前提分支,在进入这些前提分支后,就马上让函数退出。有一个罕见的技能。在面临一个嵌套的if分支时,我们能够把外层if表达式举行反转。比方:
var del = function(obj) {
if (obj.isReadOnly) { // 反转表达式
return;
}
if (obj.isFolder) {
return deletFolder(obj);
}
if (obj.isFile) {
return deletFile(obj);
}
}
通报对象参数替代太长的参数列表
函数能够接收多个参数,参数越多函数就越难明白和运用。
setUserInfo(1111, 'sven', 'hangzhou', 'male', '137*****')
// 可改写成
setUserInfo({
id: 1111,
name: 'sven',
address: 'hangzhou',
sex: 'male',
mobile: '137*****'
})
改写后能够不再体贴参数的数目和递次,平常参数控制在4个之内,凌驾4个就须要转化成对象情势。
合理运用链式挪用
链式挪用在调试的时刻异常不方便,假如一条挪用链中有毛病涌现,必须要把这条挪用链拆开才定位毛病涌现的处所。
假如该链条的构造稳固,后期不容易发作修正,运用链式挪用无可厚非,然则假如该链条轻易发作变化,致使调试和保护难题,那末一般挪用情势为佳。
剖析大型类
假如一个类的要领充足庞杂和巨大,那末它完整有必要作为一个零丁的类存在。面向对象设想勉励将行动散布在合理数目的更小对象当中。
用return退出多重轮回
在函数有两重轮回语句时,我们每每须要在内层轮回中推断,当到达临界前提时退出外层轮回,有以下完成体式格局。
设置flag。
var func = function() {
var flage = 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() {
outerloop:
for(var i = 0; i < 10; i++) {
innerloop:
for(var j = 0; j < 10; j++) {
if (i * j >30) {
break outerloop;
}
}
}
}
这两种做法都让人头晕目眩,更简朴的做法是直接停止全部要领:
var func = function() {
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i * j > 30) {
return;
}
}
}
}
用return
直接退出有一个题目,在轮回以后假如另有代码就没法实行:
var func = function() {
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i * j > 30) {
return;
}
}
}
console.log(i); // 没法实行
}
我们能够把轮回后须要的代码放到return
背面,假如代码较多,能够提炼成一个零丁的函数。
var print = function(i) {
console.log(i);
};
var func = function() {
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i * j > 30) {
return print(i);
}
}
}
};