对同一个表达式稍加改动就会打乱表达式的逻辑运算顺序,因此我们应该学会优化表达式的结构,不改变表达式的运算顺序和结果即可提高代码的可读性。
1.第一种方式——加小括号
例如,面对下面这个复杂表达式,可能被&&和||的优先级所迷惑。
(a+b>c&&a-b<c||a>b>c)
不过,如果进行如下优化,逻辑运算的顺序就会非常清晰了。
((a+b>c)&&((a-b<c)||(a>b>c)))
虽然增加这些小括号显得多余,但是这么写并没有影响表达式的实际运算,反而带来了非常明显的好处。学会使用小括号分隔符来分隔表达式的逻辑层次,不失为一种高明之举。
使用小括号分隔符来优化表达式内部的逻辑层次,是一种很好的设计习惯。如果复杂表达式中存在一些与人的思维方式相悖的不良的逻辑结构,也会影响人们对代码的阅读和思考,这个时候就应该根据人的思维习惯来优化表达式的逻辑结构。
2.第二种方式——改变表达式结构顺序
例如,想设计一个表达式来筛选学龄人群,即年龄大于或等于6岁且小于18岁的人:
if(age>=6&&age<18){
}
直观阅读,表达式age>=6&&age<18可以很容易被每一个人所理解。继续复杂化表达式:筛选所有弱势年龄人群,以便在购票时实施半价优惠,即年龄大于或等于6岁且小于18岁,或者年龄大于或等于65岁的人:
if(age>=6&&age<18||age>=65){
}
从逻辑上分析,上面表达式没有错误。但是从结构上分析就感觉比较模糊,为此我们可以使用小括号来分隔逻辑结构层次,以方便阅读。
if((age>=6&&age<18)||age>=65){
}
但是,此时如果根据人的思维来思考条件表达式的逻辑顺序时,会发现它有些紊乱,与人的一般思维方式发生了错位。人的思维是一种线性的、有联系、有参照的一种方式,如图1.1所示。
图 1.1 人的思维模型图对于表达式(age>=6&&age<18)||age>=65来说,其思维模型图如图1.2所示。通过对此模型图的直观分析,会发现该表达式的逻辑是非线性的,呈现多线思维的交叉型,这种思维结构对于机器计算来说基本上没有任何影响。但是对于人脑思维来说,就需要认真思考之后,才能把这个表达式中各个小的表达式逻辑单元串联在一起,形成一个完整的逻辑线。
图 1.2 表达式的思维模型图直观分析,这个逻辑结构的错乱是因为随意混用大于号和小于号等运算符造成的。如果调整一下表达式的结构顺序,阅读起来就非常清晰了。
if((6<=age&&age<18)||65<=age){
}
这里采用了统一的小于号方式,即所有参与比较的项都按着从左到右、从小到大的思维顺序进行排列,而不再遵循变量始终居左、比较值始终居右的传统编写习惯。
3.第三种方式——避免布尔表达式的叠加
表达式中的另一个“顽疾”是布尔型表达式的重叠所产生的迷宫。在复杂表达式中,这种多重叠加的布尔表达式足以“令人生畏”。例如,对于下面这个条件表达式:
if!(!isA||!isB){
}
如果采用“剥洋葱皮”的方法逐层分析,也可以找到结果。当然,也可以对这样的表达式进行优化,以方便阅读。例如:
(!isA||!isB)=!(isA&&isB)
(!isA&&!isB)=!(isA||isB)
?运算符为很多程序员所喜爱,特别是在JavaScript函数式编程中,这个运算符的使用频率会更高。但对于很多开发者来说,由于难以适应这种连续思维,会在阅读代码时产生障碍。为此,可以适当采用if条件语句对?运算符表达式进行分解。
4.第四种方式——if语句分解
例如,对于下面这个复杂表达式,如果不仔细进行分析,很难理清它的逻辑顺序。
var a.b=new c(a.d?a.e(1):a.f(1))
在使用if条件语句后,逻辑结构就变得非常清晰了。
if(a.d){
var a.b=new c(a.e(1));
}else{
var a.b=new c(a.f(0));
}