这是一个持续跟新的文章。
这篇文章会记录下我对代码重构的思考和读书的总结。
1.提炼函数
- 在JavaScript开发中,我们大部分时间都在与函数打交道,所以我们希望这些函数有良好的命名,函数体内包含的逻辑清晰明了。
- 如果一个函数过长,不得不加上若干注释才能让这个函数显得易读一些,那这些函数就很有必要进行重构。
- 如果在函数中有一段代码可以被独立出来,那我们最好把这些代码放进另外一个独立的函数中,好处有如下几点。
- 避免出现超大函数。
- 独立出来的函数有助于代码复用。
- 独立出来的函数更容易被覆写。
- 独立出来的函数如果有一个良好的命名,它本身就起到了注释的作用。
var getUserInfo = function () {
ajax('http:// xxx.com/userInfo', function (data) {
console.log('userId:' + data.userId);
console.log('userName:' + data.userName);
console.log('nickName:' + data.nickName);
});
};
改成:
var getUserInfo = function () {
ajax('http:// xxx.com/userInfo', function (data) {
printDetails(data);
});
};
var printDetails = function (data) {
console.log('userId:' + data.userId);
console.log('userName:' + data.userName);
console.log('nickName:' + data.nickName);
}
2.合并重复的条件片段
var paging = function (currPage) {
if(currPage <= 0){
currPage = 0;
jump(currPage);
}else if(currPage >= totalPage){
currPage = totalPage;
jump(currPage);
}else{
jump(currPage);
}
};
可以看到,负责跳转的代码jump(currPage)在每个条件分支内都出现了,所以完全可以把这句代码独立出来。
var paging = function (currPage) {
if(currPage <= 0){
currPage = 0;
}else if(currPage >= totalPage){
currPage = totalPage;
}
jump(currPage);
};
3.把条件分支语句提炼成函数
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;
};
4.提前让函数退出代替嵌套条件分支
许多程序员都有这样一个观念:“每个函数只能有一个入口和一个出口。”现代编程语言都会限制函数只有一个入口。但关于“函数只有一个出口”,往往会有一些不同的看法。
下面这段伪代码是遵守“函数只有一个出口”的典型代码:
var del = function (obj) {
var ret;
if(!obg.isReadOnly) {
if(obj.isFolder) {
ret = deleteFolder(obj);
}else if (obj.isFile){
ret = deleteFile(obj);
}
}
return ret;
}
用《重构》中的话说,嵌套的条件分支往往是由一些深信“每个函数只能有一个出口的”程序员写出的。
但实际上,如果对函数的剩余部分不感兴趣,那就应该立即退出。
引导阅读者去看一些没有用的else片段,只会妨碍他们对程序的理解。
var del = function (obj) {
if(obj.isReadOnly){
return;
}
if(obj.isFolder){
return deleteFolder(obj);
}
if(obj.isFile){
return deleteFile(obj);
}
}