一次重构angular1.x代码建议收集(这可能是一篇过时的文章了)
html中没用到的变量不要挂载在$scope上
1 | $scope.getQueryParams = function () {};//错误 |
getQueryParams
只在js文件中被调用,就不应该挂在$scope上。
优化篇
1 | $scope.cancelVerify = function (contract) { |
以下是纯js建议跟 angular关系不大
将代码写到你不能再优化为止
1 | $scope.changeTimeType = timeType => { |
以下代码一定是CV战士写的。居然还懂得用$.grep的方法
1 | //收集过滤条件 |
重构后还是don't repeat yourself
1 | parms.status = chain($scope.filterDataStatus).find("selected").get("value").value() |
图中的chain
是lodash
中的方法,不吹不黑,lodash
在数据处理方面还是比jquery
高不是一个档次的。如果不是名字瞎命名的话,一个琏式表达式就能解决了。
去掉无用的注释代码
1 | //下拉框处理 |
以上注释只是被当作了历史的记录工具存在。而更好的方法去代替这段代码的的是去学习使用git。注释应该去掉。1
2
3
4
5
6
7
8
9
10
11//操作
//提交复核
$scope.submitVerify = function (contract) {};
//取消复核
$scope.cancelVerify = function (contract) {};
//确认复核
$scope.confirmVerify = function (contract) {};
//作废
$scope.cancelContract = function (contract) {};
//删除
$scope.deleteContract = function (contract) {};
以上注释并不能提供更多理解代码的信息。一个好的函数签名就可以表明意图。注释应该去掉。
1 | /** |
以上代码 注释部分是完全多余的,而该注释的地方却没有注释出来。
参数的名称也非常的晦涩。
日期本身就可以比较。
存在部分重复的代码。
关于最后的if else
只能说,精益求精。
重构后1
2
3
4
5
6const toDate = str => {
const arr = str.split("-");
return new Date(arr[0], arr[1], arr[2]);
}
//dateStr1 and dateStr2 is a formatted string like yyyy-MM-dd
const compareDate = (startDate, endDate) => toDate(startDate) > toDate(endDate)
缺点是多暴露了一个toDate
函数,这一点可以用模块化或者闭包的方法去解决。
吐槽
看到有return o.selected === true;
的代码。js虽然是弱类型语法,但是如果严格一点,能确保selected
是bool值
的话 完全可以写成return o.selected
。
次日新增如下内容
1 | const appPrices = []; |
使用lodash
重构如下1
2
3
4
5
6
7
8
9
10
11
12import { map } from 'lodash'
$dialogScope.ddlConfigSMSPrice = {
allowClear: false,
data: map(item.applicationPrices , ({ price,unit })=>({
id: price,
text: unit
})),
placeholder: '标准单价',
onchange2(price) {
$dialogScope.data.unit = price.text;
}
};
map
方式总会返回正确的类型。不需要花哨的代码去判断undefined
。
类似代码还有如下1
2
3
4
5
6
7
8
9
10
11
12const ddlData = [];
let isCompanyValid = false;
$.each(data, function (i, d) {
ddlData.push({
id: d.company_id,
text: d.company_name
});
if (d.company_id === $scope.contractBaseInfo.company_id) {
isCompanyValid = true;
}
});
$scope.ddlConfigCompany.data = ddlData;
理论上我觉得isCompanyValid
与ddlData
应该分别处理而不应该合在一起处理的1
2
3
4
5const isCompanyValid = findIndex(data,['company_id',$scope.contractBaseInfo.company_id]) !== -1
$scope.ddlConfigCompany.data = map(data, ({ company_id, company_name }) => ({
id: company_id,
text: company_name
}));
findIndex(data,['company_id',$scope.contractBaseInfo.company_id])
这个函数会处理data里面的每一个元素,找到属性company_id
为$scope.contractBaseInfo.company_id
的元素下标并返回,如果找不到就返回-1
。虽然的函数的签名很奇怪,但是读懂后使用会很方便。
部分人可能觉得性能会有问题。个人觉得这点小性能实在不应该成为代码规范的拦路石。如果实在有强迫症的人可以采取折中的方法。1
2
3
4
5
6
7
8let isCompanyValid = false
$scope.ddlConfigCompany.data = map(data, ({ company_id, company_name }) => {
isCompanyValid = company_id === $scope.contractBaseInfo.company_id
return {
id: company_id,
text: company_name
}
});
这可能违反了只做一件事的原则
,当一个函数做了两件事三件事更多件事的时候。我们在处理一件事的时候就会被其它的事干扰到。而人的精力是有限的。被干扰的后果是不知不觉的引进了bug
所以保证你的函数简单是最好的方法。
有的人可能觉得函数编程比较难看懂,比如const isCompanyValid = findIndex(data,['company_id',$scope.contractBaseInfo.company_id]) !== -1
。那是因为一句话做了太多的事情了。1
2const includesWithPropertyEq = compose(eq(-1),findIndex);
const isCompanyValid = includesWithPropertyEq(data,['company_id',$scope.contractBaseInfo.company_id]);
利用函数的组合可以把多件事情组合成一个函数。然后通过命名让别人知道你的函数是作用。(以上代码假装eq
是柯里化
的
1 | const ddlData = []; |
代码本身有注释非常好,让人知道那一串7f84cfad-fce8-11e4-bed8-00155d02c832
是个什么玩意。如果没有注释的话一定要记得取个好名字比如。const aGoodName = '7f84cfad-fce8-11e4-bed8-00155d02c832'
(示例而已,你自己就不要起aGoodName
了)
但是代码本身做的事其实就是filter
,或者reject
(reject
与filter
是反逻辑的),所以:
1 | // 隐藏 |
如果你还记得上面那个奇怪的签名。那也能理解这个签名。
reject(data,['property_id','7f84cfad-fce8-11e4-bed8-00155d02c832']
的意思是把data
里面,属性property_id
为7f84cfad-fce8-11e4-bed8-00155d02c832
的元素去掉。与reject(data,({property_id})=>property_id === '7f84cfad-fce8-11e4-bed8-00155d02c832')
是等价的,filter(data,({property_id})=>property_id !== '7f84cfad-fce8-11e4-bed8-00155d02c832')
实现了相同的功能。(因为reject
与filter
是反逻辑的)
上面的代码还是有问题的,因为原代码做了一个命名的转换,但是我们没有做。
修改后如下1
2
3
4$scope.ddlConfigContractNature.data = chain(data)
.reject(['property_id', '7f84cfad-fce8-11e4-bed8-00155d02c832'])
.map(({ property_id, property_name }) => ({ id: property_id, text: property_name }))
.value();
chain
做了打包,是一个很好的琏式调用,记录最后要用value来解包
不管怎么说,能少写一行代码 就少写一行代码
虽然原代码,多看一下也能理解,但是大量的更容易理解的代码与多看一眼能理解的代码,对人的影响就绝不是多看一眼的影响了。