如果表达式

时间:2016-09-06 21:40:31

标签: javascript angularjs if-statement expression

我刚刚加入了一个具有angularJS前端的大型电子商务项目。我的任务是在结帐页面添加许多复杂的功能......这些功能已经有很多复杂的逻辑。

为了让事情变得更难我继续遇到许多if语句表达式,如下面的表达式使得它很难理解,这是一个很慢的过程,通过这段代码来处理这些类型{{1表达式。

其中一些表达非常关键,有时甚至更长......没有单元测试,当我向其他开发人员询问这是检查什么以及为什么(只是为了确定我理解)时,我通常会指向某人否则不是解释。

if

有没有人有很好的重构这些类型的表达式?

我想把它们分解成具有描述性名称的函数,函数可以返回if ((!previousBillingAddress) || (previousBillingAddress && previousBillingAddress.id !== bag.paymentAddress.id)){ console.log('all of the above was true'); // just a dummy log } else { console.log('all of the above was false'); // just a dummy log } true,但我不确定是否有更好的方法。

6 个答案:

答案 0 :(得分:1)

您可以删除previousBillingAddress &&部分 - 在您已经发布的||的第二个操作数中previousBillingAddress不是假的。这将使整体状况

if (!previousBillingAddress || previousBillingAddress.id !== bag.paymentAddress.id) {
    console.log('all of the above was true'); // just a dummy log
} else {
    console.log('all of the above was false'); // just a dummy log
}

这对我来说似乎很短。如果没有,请为您传递previousBillingAddressbag

答案 1 :(得分:1)

让它有

A = previousBillingAddress 
B = previousBillingAddress.id !== bag.paymentAddress.id

然后你的表达是:

if (!A || (A && B)) {
  log1
} else {
  log2
}

!A || (A && B)我们可以做些什么?它等于!A || B

A   |  B  |  !A  |  A && B  |  !A || (A && B)  |  !A || B
==========================================================
1   |  1  |   0  |    1     |        1         |     1
1   |  0  |   0  |    0     |        0         |     0
0   |  1  |   1  |    0     |        1         |     1
0   |  0  |   1  |    0     |        1         |     1

这就是为什么你的表达式等于:

if (!previousBillingAddress || previousBillingAddress.id !== bag.paymentAddress.id) {
    console.log('all of the above was true'); // just a dummy log
} else {
    console.log('all of the above was false'); // just a dummy log
}

<强> TL; DR

上表仅检查!A || (A && B)是否等于!A || B。如何猜测!A || B?如果有这样的表达,遵循以下规则是很好的:

A == !(!(A))                        (rule 1)
!(A && B) == !A || !B               (rule 2)
!(A || B) == !A && !B               (rule 3)
A && (B || C) == A && B || A && C   (rule 4)

所以我们有!A || (A && B),让我们玩。由于规则1,它等于

!(!(!A || (A && B)))

现在我们使用规则3:

!(!(!A || (A && B))) == !(A && !( A && B))

规则2:

!(A && !( A && B)) == !(A && (!A || !B))           (*)

由于规则4:

A && (!A || !B) == (A && !A) || (A && !B) 

我们有(A && !A) || (A && !B),可以缩减为(A && !B)。现在我们可以回到(*),我们有:

!(A && (!A || !B)) == !((A && !A) || (A && !B)) == !(A && !B)

根据规则2,我们得到了:

!(A && !B) == !A || B

答案 2 :(得分:0)

评论是我们最好的朋友。你想确保下一个看你的代码的人知道到底应该做什么,从那里,它会更快更容易看到到底是什么做即可。

在这种情况下,可以缩短if语句中的表达式。这就是我几乎用伪代码方法对它进行评论的方法:

// we need to check if the user has, and is using, a previous billing address
if (previousBillingAddress && previousBillingAddress.id === bag.paymentAddress.id)){

    // the user is using a previous billing address

    // do some work with the previous billing address

} else {

    // the user is using a new address

    // do some work with the new address

    // save the new billing address

}

请注意,previousBillingAddress是此if语句的主要主题。如果我们正在检查previousBillingAddress,那么在我们的第一个块中,我们要确保我们处理如果我们有的话会发生什么以前的帐单邮寄地址。这种方式更符合逻辑。

检查我们是否没有以前的帐单地址,然后如果我们有一个帐单,我们会怎么做。

看看它是多么干净和合乎逻辑! &LT; 3

答案 3 :(得分:0)

在我个人看来,我认为您可以重构并封装函数内部的验证/检查,如果相同的验证适用于您的代码的其他部分(文件/模块/等......),您可以重复使用它。在这种情况下,您使用的是角度,因此可能最好使用角度自定义服务进行此类业务验证,因为它们也可以操作范围

答案 4 :(得分:0)

我建议将复杂条件提升为布尔变量(或常量,如果您支持的JS级别允许您使用const)。例如:

var weakPrevBillingAddress = 
      !previousBillingAddress || 
      (previousBillingAddress && 
        (previousBillingAddress.id !== bag.paymentAddress.id));

if (weakPrevBillingAddress) {
  console.log('judged weak previousBillingAddress');
  // other processing expected here
} else {
  console.log('judged strong previousBillingAddress');
  // other processing expected here
}

正如您和philip yoo建议的那样,您可以将条件提升为布尔辅助函数。但是,定义这些函数的大多数方法都会使逻辑远离使用点,使理解变得更加困难。布尔变量(a.k.a。“谓词”)可以很容易地定义在它们的使用附近(例如在你的if语句之前)。因此没有太多的额外距离,但它们仍然将布尔值的计算与其使用分开。您单独关注计算的能力可以使事情变得更简单,更易于理解。如上所示,它还允许您拆分很长时间 线条和使用缩进以获得更好的清晰度。

我不知道您是否可以灵活地重命名现有变量名称。如果你这样做,你使用的那些是非常长的。长名称可以帮助增加理解,但每行重复多次22个字符的名称会分散注意力,而不是澄清。较短的名称(无论是源值还是仅针对您计算的谓词)都可以提供帮助。 E.g:

var weakPrevBA = !prevBA || 
      (prevBA.id !== bag.paymentAddress.id);

选择好的变量名称是一门艺术,开发人员对“多少描述就足够”的看法有所不同。但是在一个一直处理结算地址的应用中,一行接一行,每次拼写billingAddress并不一定有帮助。如果您正在阅读代码和评论,您可能非常清楚您正在处理帐单地址。如果没有,请添加快速评论,而不是每行多次拼出完整概念。

请注意,我在这个较短的示例中也简化了布尔表达式。 (这也是suggested by Bergi)这可能是一个好主意 - 只要你确定它可以正确简化。但是,这只是非常谨慎。您没有单元测试,因此您无法轻松测试简化是否完全相同。而且你正在处理复杂的代码。我建议保留原始的布尔表达式,至少要开始(可能有缩短的名称)。这减少了一个地方可能出现的错误,至少在你更充分地理解代码之前。你理解代码越好,你做得越简单(例如通过添加计算谓词,而不是条件句中的长复杂表达式),你在重写表达式时就会有更多的自由和安全。

答案 5 :(得分:-1)

像这样的东西

var billingId = previousBillingAddress && previousBillingAddress.id;

if (billingId || billingId === bag.paymentAddress.id){
    console.log('all of the above was false'); // just a dummy log
} else {
    console.log('all of the above was true'); // just a dummy log
}

我做了什么

  1. 因为您使用的是ifelse,所以在if语句中使用否定并不是一个好习惯。所以我删除了
  2. 如果您只想要否定部分(没有其他)

    if (!(billingId || billingId === bag.paymentAddress.id)){
        console.log('all of the above was true'); // just a dummy log
    }
    
    1. &amp;&amp;将返回第一个false或最后一个true值。因此billingId将等于falseid。在此基础上,你的第一个if是检查"falsey"是否继续,所以你也可以使用相同的变量。