重构代码的tricks

js的设计模式是针对于总体代码的设计是否合理,给出了一些具体的解决办法。 而重构代码就是依赖于设计模式而实现的一个必要手段,能够说设计模式就是重构代码的目标,但他的手段却不只仅只有设计模式这些大而全的,一样存在小而精,咱们随处可使用的。css

封装功能块代码

咱们一般在写代码的时候,一开始,并不须要考虑太多。在后期能够进行修改和提炼。 好比,我有个业务需求,是建立一个div而且渲染数据到页面上,而且根据data的不一样,改变div的状态.设计模式

function(data){
    var div = document.createElement("div"),
    div.innerHTML = data.name;
    document.body.append(div);
    if(data.isShow){
        div.style.display = "block";
    }else{
        div.style.display = "none";
    }
}

但事实上,这个函数里面还有一个代码块,就是根据data.isShow改变div的状态.咱们能够对其进行封装。app

function(data){
    var div = document.createElement("div"),
    div.innerHTML = data.name;
    document.body.append(div);
    changeState(data.isShow,div);
}
function changeState(flag,div){
    div.style.display = flag?"block":"none";
}

提取公因式

这里主要针对于,屡次重复调用同一个封装代码块函数。ide

function(flag){
    if(flag==="left"){
        move("right");
    }else if(flag==="right"){
        move("left");
    }else if(flag==="top"){
        move("bottom");
    }else if(flag==="bottom"){
        move("top");
    }
}

根据flag向反方向移动,能够看出,里面都有用到了move()这个方法,要知道,分支语句是最不利于程序阅读的,并且咱们要尽量的减小和简化分支语句里面的程序量,让阅读者耗费在分支语句上的时间降到最少。上面代码能够这样写。函数

function(flag){
    var dir;
    if(flag==="left"){
        dir = "right";
    }else if(flag==="right"){
        dir = "left";
    }else if(flag==="top"){
        dir = "bottom";
    }else if(flag==="bottom"){
        dir = "top";
    }
    move(dir);
}

恩,固然,这样写也是违反人性的。咱们可使用命令模式进行重构。
这就涉及到另一个tip.性能

将分支转化为函数

上面代码里面的分支彻底可使用函数来进行代替。优化

function(flag){
    command.flag;
}
var command = (function(){
    var left = function(){
        move("right");
    }
    var right = function(){
        move("left");
    }
    var top = function(){
        move("bottom");
    }
    var bottom = function(){
        move("top");
    }
    return {
        left,right,top,bottom
    }
})();

这样,虽然增长了一个对象,可是代码确实清晰可见的。 这就是经过命令模式,来重构代码,完成性能和阅读的优化。
但有时候,使用分支,会比这样更简洁,那固然可使用分支啦。 而使用分支还要主意一个tip就是.this

不要过分嵌套

这里想说的就两点,一是,尽量不使用分支,二是,若是嵌套分支,尽可能改成不嵌套。 不使用分支的状况上面已经说了,若是使用分支,那么请不要嵌套,或者说不要过分嵌套。由于一个分支已经很难阅读了,md,你再加个嵌套,你还让不让人读了。 而解决过分嵌套的方法真的是千千万万,我这里就介绍一个比较简单的。使用return 提前退出嵌套。prototype

function move(obj){
    if(obj.isShow){
        if(obj.isTop){
            if(obj.isLeft){
                return move("TopLeft");
            }
        }else{
            return false;
        }
    }else {
        return false;
    }
}

这,看着爽不爽。 若是,我碰见这样的代码,我第一反应就是,要!死!啦!. 因此,为了让你的程序人性化,咱们可使用return 语句进行改写。 咱们能够对条件判断的逻辑进行分析,能够看出,里面若是条件不知足都是返回false,那么咱们能够将false的状况提取出来。插件

function move(obj){
    if(!obj.isShow){
        return false;
    }
    if(!obj.isTop){
        return false;
    }
    if(!obj.isLeft){
        return false;
    }
    return move("TopLeft");
}

这是这个feel。固然,追求极致的话,咱们能够看出return false,是彻底一致的,固然能够将条件合并.

function move(obj){
    if(!obj.isShow||!obj.isTop||!obj.isLeft){
        return false;
    }
    return move("TopLeft");
}

其实若是你数学学得好的话(我还行吧,嘿~嘿~嘿~)。 这样提取条件的事是垂手可得的,能够看出,上面那段古老的代码彻底能够变为如今这个样式,并且读起来,真的不是一个档次的。

减小参数数量

减小参数数量的方法,固然永远不会===1, 由于每一个人站的角度不一样,获得的答案固然也不同。因此这里只介绍两种比较通用的。

  1. 使用对象来代替参数列表。

  2. 将须要额外计算的参数忽略。

使用对象代替参数

这个最突出的特色就是在写模板的时候。

function templ(name,age,gender){
    return `my name is ${name}. and I'm ${age} years old. yeah! I am a ${gender}`;
}

有一个模板,上面需求的参数有三个,可是,事实上,这个是彻底不靠谱的。 由于一我的不只仅只有name,age,gender 确定还有别的参数,这样,形成的后果就是,你一直在维护模板的同时,还须要维护参数列表。并且,还要维护,传入参数的顺序的正确性。因此这里强烈推荐使用对象来代替多参数。

function templ(person){
    return `my name is ${person.name}. and I'm ${person.age} years old. yeah! I am a ${person.gender}`;
}

如今这个模板函数与外界的耦合性已经下降了很多。并且很是易于维护,就算外面你的person对象有多余的参数,也不会妨碍我使用我须要的数据。

忽略额外计算的参数

这种状况主要是在作UI的时候可能会遇到,即,想绘制一个数据table的时候,须要将一个数据矩形的高,宽以及面积传入一个函数,进行绘制。

function column(width,height,square){
    console.log("矩形的宽度为"+width);
    console.log("矩形的高度为"+height);
    console.log("矩形的面积为"+square);
}

而,这样作是彻底没有必要的,由于函数参数越少,给人的感受固然越好。
咱们能够修改成这样.

function column(width,height){
    var square = width*height;
    console.log("矩形的宽度为"+width);
    console.log("矩形的高度为"+height);
    console.log("矩形的面积为"+square);
}

并且在插件设计中,也应该准遵照这个原则,函数的参数应该在能力范围内,把它降至最少。

链式调用

这个应该算是比较高级的用法。使用过jQuery的同窗应该印象最深入。 即,咱们能够这样来使用一个功能.

$(".myClass").addClass("show").attr('data-name').css("display","none");

而这样实现其实并不难,只要在每一个方法的后面返回该对象就能够实现这个技能。
咱们来模仿一下。

var Div = function(){

}
Div.prototype.createElement = function(){
    console.log("建立一个Div");
    return this;
}
Div.prototype.showDiv = function(){
    console.log("显示Div");
    return this;
}
var div = new Div();
div.createElement().showDiv();

这样不只能够实现对象的细粒度,并且也知足单一职责原则。
一样,我要说的是,觉得的使用链式的时候,记住,使用一个功能块链式调用必定要分行,否则,调bug会调哭的。

var Div = function(){

}
Div.prototype.createElement = function(){
    console.log("建立一个Div");
    return this;
}
Div.prototype.showDiv = function(){
    console.log("显示Div");
    return this;
}
Div.prototype.hideDiv = function(){
    console.log("隐藏Div");
    return this;
}
Div.prototype.tagName = function(){
    console.log("tagName 是 Div");
    return this;
}
var div = new Div();
div.createElement().showDiv().tagName().hideDiv();  //表这样作

上面是个反例,正确的作法,应该分开。

div.createElement()
.showDiv()
.tagName()
.hideDiv();

像这样调用,万一出个Bug,你也应该知道这个bug在哪个函数块内。大部分重构的小技巧差很少介绍完了(智商有限),若是,你们有什么更好的建议欢迎留言反馈.

相关文章
相关标签/搜索