在逻辑运算符两侧使用多个条件的if语句

5

我正在尝试在逻辑运算符的两侧使用多个参数的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 代码,会失败。 - adeneo
(a || b) == 'banana' 应该改为 (a == 'banana' || b == 'banana')。 - SajithNair
2
顺便提一下,你可以这样写:if ( /(banana|apple)/.test(a) ) - adeneo
我以前从未听说过 .test() 方法!@adeneo - AKG
你的代码很短,易读。我认为你不需要再缩短它。 - Mahdi
@AKG - 这是用于测试正则表达式的工具,有时非常方便。在MDN上可以找到它。 - adeneo
5个回答

3
逻辑或运算符并不是你所期望的那种方式工作。

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

MDN

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

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

另一件你可以做的事情是使用 in 运算符。由于它只检查键值,你可以像这样保留空的 values
if ( a in { "apple": "", "banana": "" } ) { ... }

如果您有很多选项,显然最好采取以下做法:
var options = {
    "apple": "",
    "banana": ""
}

if ( a in options ) { ... }

我个人认为,只有两个选项需要检查时,将它们分开检查会更易读。我认为在您的示例中,不需要缩短if语句,因为在我看来它们已经相当简短和易读。

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

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个元素并链接过滤器,则可以稍微减少一些。例如:http://jsfiddle.net/aYRmL/2/ - elclanrs
@elclanrs,这只是我脑海中的一个快速想法。现在已经修复了。 - aleclarson

0

作为替代方案,您可以使用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)) {
  ...
}

0

(a || b) == 'banana'总是会返回false,因为(a || b)将返回一个布尔值,而不是一个字符串

更新: 进行了一些测试,(a || b)总是返回第一个操作数(在这种情况下是a),它不等于'banana'。

||和&&只有在两个操作数都是布尔值或可以转换为布尔值时才会给出预期的结果。


1
JavaScript的||并不总是返回布尔值。它将按原样返回ab的值。console.log(1 || 2);输出1,而不是true - Jonathan Lonowski
2
由于短路求值 - elclanrs

0

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

ab都是字符串时,它们永远不会为false,除非字符串长度为零。因此,在您的情况下,a || b将是“apple”,a && b将是“banana”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接