【问题标题】:Multiple conditions in if statement on both sides of the logical operator逻辑运算符两边的if语句中的多个条件
【发布时间】:2014-04-03 06:15:33
【问题描述】:

我正在尝试在逻辑运算符两侧的 if 语句中使用多个参数。我首先从 || 开始运算符,按预期工作:

var a = 'apple', b = 'banana', c = 'cherry';

if (a == 'banana' || a == 'apple' || b == 'banana' || b == 'apple') {
    console.log('example 1') // returns
}

if ((a || b) == 'banana' || (a || b) == 'apple') {
    console.log('example 2') // returns
}

if (a == ('apple' || 'banana') || b == ('apple' || 'banana')) {
    console.log('example 3') // returns
}

if ((a || b) == ('apple' || 'banana')) {
    console.log('example 4') // returns
}

到目前为止,没有意外的结果。 但是,当替换 || 时遵循类似的结构&& 运算符的运算符,事情并没有像我期望的那样工作。

if ((a == 'banana' && b == 'apple') || (a == 'apple' && b == 'banana')) {
    console.log('example 5') // returns
}

if (((a || b) == 'banana') && ((a || b) == 'apple')) {
    console.log('example 6') // DOESN'T RETURN
}

if ((a || b) == 'banana') {
    console.log('example 6a') // DOESN'T RETURN - consistent with example 6
}

if ((a == ('apple' || 'banana')) && (b == ('apple' || 'banana'))) {
    console.log('example 7') // DOESN'T RETURN
}

if (a == ('apple' || 'banana')) {
    console.log('example 7a') // returns - inconsistent with example 7
}

if (b == ('apple' || 'banana')) {
    console.log('example 7b') // DOESN'T RETURN - inconsistent with example 7a
}

if ((a && b) == ('apple' || 'banana')) {
    console.log('example 8') // DOESN'T RETURN
}

if ('apple' == (a || b) && 'banana' == (a || b)) {
    console.log('example 9') // DOESN'T RETURN
}

现在,我想知道:我的逻辑是否存在缺陷,或者不能以这种方式完成?为了可读性和可维护性,我的目标是尽可能短地编写这些 if 语句。显然我只是在探索可能性。

有谁知道解决这个问题的方法吗?尤其是示例 7/7a/7b 对我来说似乎很奇怪,因为尽管结构相似,但它产生的结果不一致 [Fiddle]

【问题讨论】:

  • 不,不能那样做,(a||b) == something 不是有效的 javascript 并且失败。
  • (a || b) == 'banana' 应该是 (a == 'banana' || b == 'banana')
  • 作为旁注,你可以做if ( /(banana|apple)/.test(a) )
  • 我以前从未听说过 .test() 方法! @adeneo
  • 您所拥有的内容非常简短易读。您无需缩短 IMO。

标签: javascript if-statement logical-operators multiple-conditions


【解决方案1】:

如果您想要一种简洁的方法来检查一个变量是否等于许多其他变量中的任何一个,请尝试使用如下函数:

http://jsfiddle.net/aYRmL/

function equalsAny (first) {
    return !![].slice.call(arguments, 1).filter(function (val) {
        return first === val;
    }).length;
}

第一个参数是与其余参数进行比较的参数。像这样使用它:

var a = 'banana', b = 'orange';
equalsAny(a, 'banana', 'apple'); // returns true
equalsAny('orange', a, b); // returns true

上面的第一个完成了您尝试使用a == ('banana' || 'apple') 执行的操作。秒数完成了您尝试使用 (a || b) == 'banana' 执行的操作。

【讨论】:

  • 如果将第一个参数作为实际参数传递,则可以减少一点,然后切片数组的 1 个元素并链接过滤器。即jsfiddle.net/aYRmL/2
  • @elclanrs 是的,这只是我头脑中的一个匆忙。现已修复。
【解决方案2】:

Logical OR 运算符无法以您想要的方式工作。

如果可以转换为true则返回expr1;否则,返回 expr2。因此,当与布尔值一起使用时,||如果任一操作数为真,则返回真;如果两者都是 false,则返回 false。

MDN

另一种方法是使用数组的indexOf 方法。请注意,它将返回数组元素的index,因此0 也可能是一个有效值。为了使我们的if 语句按预期工作,我们必须像这样使用0 <= ...

if ( 0 <= ["apple","banana"].indexOf(a) ) { ... }

您可以做的另一件事是使用in 运算符。此外,由于它仅检查 keys,因此您可以将 values 留空,如下所示:

if ( a in { "apple": "", "banana": "" } ) { ... }

如果您有很多选择,显然最好执行以下操作:

var options = {
    "apple": "",
    "banana": ""
}

if ( a in options ) { ... }

我个人认为只有两个选项来检查,这对于人眼来说进行两个单独的检查会更具可读性,而且我认为在您的示例中,您实际上不需要将 if 语句缩短为在我看来,它们已经很短且可读了。

if ( "apple" === a || "banana" === a ) { ... }

【讨论】:

    【解决方案3】:

    它的工作方式是a &amp;&amp; ba || b 始终设置为变量之一的值。 a &amp;&amp; b 将始终设置为 b 的值,除非 afalse,在这种情况下答案必须是 false。同样a || b 将设置为a 的值,除非afalse,在这种情况下它将设置为b 的值。正如 elclanrs 所提到的,这是因为短路评估 - 第一个操作数可能会决定结果,在这种情况下,查看第二个操作数是没有意义的。

    ab 都是字符串时,除非字符串长度为零,否则它们永远不会为假。所以a || b 在您的情况下将是“苹果”,而a &amp;&amp; b 将是“香蕉”。

    【讨论】:

      【解决方案4】:

      (a || b) == 'banana' 总是为假,因为(a || b) 将返回一个不等于字符串的布尔女巫

      更新: 做了一些测试(a || b) 总是返回第一个操作数(在这种情况下为a)女巫是“苹果”而不等于“香蕉”。

      ||只有当两个操作数都是布尔值或可以转换为布尔值时,&& 才会给出例外结果。

      【讨论】:

      • JavaScript 的 || 并不总是产生布尔值。它将按原样返回ab 的值。 console.log(1 || 2); 记录 1,而不是 true
      【解决方案5】:

      作为替代解决方案,您可以使用someevery

      var __slice = [].slice;
      
      function any(a) {
        return __slice.call(arguments,1).some(function(x) {
          return a === x;
        });
      }
      
      function all(a) {
        return __slice.call(arguments,1).every(function(x) {
          return a === x;
        });
      }
      

      并像这样使用:

      // Instead of:
      // if (a == 'banana' || a == 'apple' || a == 'orange')
      if (any(a, 'banana', 'apple', 'orange')) {
        ...
      }
      
      // Instead of:
      // if (a == 'banana' && b == 'banana' && c == 'banana')
      if (all('banana', a, b, c)) {
        ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多