我正在尝试在逻辑运算符两侧的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
}
到目前为止,没有出乎意料的结果。
但是,在替换||时遵循类似的结构&& amp;的操作员操作员,事情并没有像我期望的那样完成。
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]
答案 0 :(得分:2)
Logical OR
运算符无法以您正在寻找的方式运行。
如果可以转换为true,则返回expr1;否则,返回expr2。因此,当与布尔值一起使用时,||如果任一操作数为true,则返回true;如果两者都为假,则返回false。
另一种方法可以是使用数组的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 ) { ... }
答案 1 :(得分:1)
如果你想要一个干净的方法来检查变量是否等于许多其他变量中的任何一个,请尝试使用如下函数:
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'
进行的操作。
答案 2 :(得分:0)
(a || b) == 'banana'
总是假的,因为(a || b)
会返回一个布尔女巫不等于字符串
更新:
做了一些测试(a || b)
总是返回第一个操作数(在这种情况下为a
)女巫是'apple'而不等于'banana'。
||和&amp;&amp;只有当两个操作数都是布尔值或者可以被置于布尔值时才会给出例外结果。
答案 3 :(得分:0)
它的工作方式是a && b
和a || b
始终设置为其中一个变量的值。除非a && b
为b
,否则a
将始终设置为false
的值,在这种情况下,答案必须为false
。同样,a || b
将设置为a
的值,除非a
为false
,在这种情况下,它将设置为b
的值。正如elclanrs所提到的,这是因为短路评估 - 第一个操作数可能决定结果,在这种情况下,查看第二个操作数是没有意义的。
当a
和b
都是字符串时,除非字符串为零长度,否则它们永远不会为假。因此a || b
在您的情况下将为'apple',而a && b
将为'banana'。
答案 4 :(得分:0)
作为替代解决方案,您可以使用some
或every
:
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)) {
...
}