0%

代码重构


一些重构的建议:

  1. 提炼函数
* 避免出现超大函数

* 独立出来的函数有助于代码复用

* 独立出来的函数更容易被覆写

* 独立出来的函数如果拥有一个良好的命名,

* 它本身就起到了注释的作用。

比如在一个负责取得用户信息的函数里面,我们还需要打印跟用户信息有关的log,那么打印log的语句就可以被封装在一个独立的函数里:


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);
}

  1. 合并重复的条件片段
    如果一个函数内有一些条件分支语句,而这些条件分支语句内部散步了一些重复的代码,那么就有必要进行合并去重工作。


//页面跳转
var paging = function(currPage) {
if (currPage <= 0) {
currPage = 0;
jump(currPage); //跳转
} else if (currPage >= totalPage) {
currPage = totalPage;
jump(currPage); //跳转
} else {
jump(currPage); //跳转
}
}

改成


//页面跳转
var paging = function(currPage) {
if (currPage <= 0) {
currPage = 0;
} else if (currPage >= totalPage) {
currPage = totalPage;
}
jump(currPage); //跳转
}

  1. 把条件分支语句提炼成函数
    在程序设计中,复杂的条件分支语句是导致程序难以阅读和理解的重要原因,而且容易导致一个庞大的函数,所以通常我们要进行一定的提炼。


//计算商品价格,如果处于夏季,全部商品八折出售
var getPrice = function(price) {
var date = new Date();
if (date.getMonth() >= 6 && date.getMonth <= 9) { //夏季
return price * 0.8;
}
return price;
}

改成


//计算商品价格,如果处于夏季,全部商品八折出售
var getPrice = function(price) {

    if (isSummer()) { //夏季
        return price * 0.8;
    }
    return price;
}
var isSummer = function() {
    var date = new Date();
    return date.getMonth() >= 6 && date.getMonth <= 9;
}
  1. 合理使用循环
var createXHR = 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 = createXHR();

改成:


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 ActiveObject(version);
} catch(e) {

        }
    }
};
var xhr = createXHR();
  1. 提前让函数退出代替嵌套条件分支
var del = function(obj) {
    var ret;
    if (!obj.isReadOnly) { //不为只读的时候才可以删除
        if (obj.isFolder) { //如果是文件夹
            ret = deleteFolder(obj);
        } else if (obj.isFile) { //如果是文件
            ret = deleteFile(obj);
        }
    }
    return ret;
}

改成:


var del = function(obj) {
if (obj.isReadOnly) {
return;
}
if (obj.isFolder) { //如果是文件夹
return deleteFolder(obj);
}
if (obj.isFile) { //如果是文件
return deleteFile(obj);
}
}

  1. 传递对象参数代替过长的参数列表
    有时候一个函数可能接收多个参数,而参数的数量越多函数就越难理解和使用。这时我们可以把参数放入一个对象内,然后把对象传入。


var setUserInfo = function(id, name, address, sex, mobile, qq) {
console.log(‘id=’ + id);
console.log(‘name=’ + name);
console.log(‘address=’ + address);
console.log(‘sex=’ + sex);
console.log(‘mobile=’ + mobile);
console.log(‘qq=’ + qq);
}
setUserInfo(1234, cyseria, guangzhou, female, 188***, 52***);

改成:


var setUserInfo = function(obj) {
console.log(‘id=’ + obj.id);
console.log(‘name=’ + obj.name);
console.log(‘address=’ + obj.address);
console.log(‘sex=’ + obj.sex);
console.log(‘mobile=’ + obj.mobile);
console.log(‘qq=’ + obj.qq);
}
setUserInfo({
id: 1234,
name: cyseria,
address: guangzhou,
sex: female,
mobile: 188***,
qq: 52***
});

  1. 尽量减少参数数量
    尽量减少一些没必要的不会使用或者可以求出的参数。这里不做过多阐述。

  2. 少用三目运算
    有时候我们用三目运算会觉得它性能高,代码量少。但是在实际开发中,即使把一段代码循环一百万次,使用三目运算和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;
}

当然,如果只是简单的一句,用一下也没什么所谓。

  1. 合理使用链式调用
    使用jq的对链式调用一定不陌生,在自己编写函数的时候也可以使用这点,返回自身。但是他也有一个坏处,调试的时候不方便。所以如果链条的结构稳定后期不易修改,那么使用他无可厚非,但是如果该链经常发生变化那么还是用普通的调用吧。


var User = {
id: null,
name: null,
setId: function(id) {
this.id = id;
return this;
},
setName: function(name) {
this.name= name;
return this;
}
};
console.log(User.setId(1234).setName(‘cyseria’));

  1. 分解大型类
var Spirit = function(name) {
    this.name = name;
};
Spirit.prototype.attack = function(type) {
    if (type === 'waveBoxing') {
        console.log(this.name + ':使用波动拳');
    } else if (type === 'whirlKick') {
        console.log(this.name + ':使用旋风腿');
    }
};
var Spirit = new Spirit('AAA');
Spirit .attack('waveBoxing');
Spirit .attack('whirlKick');

改成:


var Attack = function(spirit) {
this.spirit = spirit;
};
Attack.prototype.start = function(type) {
return this.list[type].call(this);
}
Attack.prototype.list= function(type) {
waveBoxing: function() {
console.log(this.spirit.name + ‘:使用波动拳’);
},
whirlKick: function() {
console.log(this.spirit.name + ‘:使用旋风腿’);
}
};
var Spirit = function(name) {
this.name = name;
this.attackObj = new Attack(this);
};
Spirit.prototype.attack = function(type) {
this.attackObj.start(type);
};

var Spirit = new Spirit('AAA');
Spirit .attack('waveBoxing');
Spirit .attack('whirlKick');
  1. 用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);
}
}
}
};
func();

我知道是不会有人点的,但万一有人想不开呢?