代码重构是为了改善现有的代码设计,让代码更好。作为读书笔记,这里摘录《javascript设计模式与开发实践》中的代码重构部分。
提炼函数
避免出现超大函数。
独立出来的函数有助于代码复用。
独立出来的函数更容易被覆写。
独立出来的函数如果拥有一个良好的命名,它本身就起到了注释的作用。(代码即注释,高逼格的代码)
合并重复的条件片段
如果一个函数体内有一些条件分支语句,而这些条件分支语句内部散布了一些重复的代码,那么久有必要进行合并去重工作。DRY(don't repeat yourself)。
eg.
function paging(currPage){
if(currPage <= 0){
currPage = 0;
jump(currPage);
}else if(currPage >= totalPage){
currPage = totalPage;
jump(currPage);
}else{
jump(currPage);
}
}
以上代码中jump方法在每个条件里都出现了,这种情况就可以把它独立出来。可改成如下代码。
function paging(currPage){
if(currPage <= 0){
currPage = 0;
}else if(currPage >= totalPage){
currPage = totalPage;
}
jump(currPage);
}
把条件分支语句提炼成函数
在程序设计中,如果条件分支语句很复杂,就会导致程序难以阅读和理解,那就有必要把条件分支语句提炼成函数,既能更准确的表达代码的意思,函数名本身又起到了注释的作用。
合理使用循环
在函数体内,如果有些代码实际上负责的是一些重复性的工作,那么合理的利用循环不仅可以完成同样的功能,还可以使代码量更少。
提前让函数退出代替嵌套条件分支
为了防止代码嵌套过深,我们应当把条件分支中不成立就退出的情况提前,反转外层if表达式。如下代码。
eg.
function check(arg){
if(!arg){
return;
}
if(isString(arg))
...
}
传递对象参数代替过长的参数列表
有时候函数可能接收多个参数,而参数越多,函数就越难理解和使用。使用该函数的人首先得搞清楚全部参数的定义,在使用的时候,还要小心翼翼,以免少传了某个参数或参数位置搞反了。总之很不方便使用和维护。
这时我们可以把参数都放入一个对象内,然后把该对象传入。函数需要的数据可以自行从该对象里获取,不用再关心参数的数量和顺序,只要保证参数对应的key值不变就可以了。
这个最熟悉的的例子就是jQuery的$.ajax()方法。参数就是参数一个对象。
尽量减少参数数量
函数参数过多,带来的困扰跟上面一样。如果一个函数不需要传入任何参数就可以使用,这种函数是深受人们喜爱的。向函数传递参数不可避免,但我们应该尽量减少函数接收的参数数量。
减少三目运算符
有些程序员喜欢大规模使用三目运算符,理由是三目运算符性能高,代码量少。我觉得我用三目运算的理由是代码量少,装逼。
三目运算符的效率和if else的效率差距可以忽略不计,相比损失代码可读性和可维护性,三目运算符节省的代码量也可以忽略不计。
如果条件分支逻辑简单且清晰,这无碍我们使用三目运算符。如果条件分支逻辑非常复杂,那最好还是写if else,那样更容易阅读和修改维护。
合理使用链式调用
jQuery的链式调用方法用起来特别爽,js中,也可以很容易的实现方法的链式调用,即让方法调用结束后返回对象本身。
为什么说要合理使用链式调用?因为链式调用带来的坏处就是在调试的时候非常不方便。如果我们知道一条链中有错误出现,必须得先把这条链拆开才能加上一些调试log或打断点,这样才能定位错误出现的地方。
如果该链条的结构相对稳定,后期不易发生修改,那么使用链式调用无可厚非。但如果该链条很容易发生变化,导致调试和维护困难,那么还是建议使用普通调用形式。
分解大类型
说到底,解耦合。尽量做到低耦合,职责单一。面向对象涉及鼓励将行为分布在合理数量的更小对象之中。
用return退出多重循环
假设在函数体内有一个两重循环语句,我们需要在内层循环中判断,当达到某个临界条件时退出外层循环。我们大多数时候会引入一个控制标记变量,或者设置循环标记。
这两种做法无疑让人头晕目眩,更简单的做法是在需要终止循环的时候直接退出整个方法。当然用return直接退出方法会带来一个问题,如果在循环之后还有一些将被执行的代码呢?如果我们提前退出了整个方法,这些代码就得不到被执行的机会。
为了解决这个问题,我们可以把循环后面的代码放到return后面,如果代码比较多,就应该把他们提炼成一个单独的函数。