我曾尝试在逻辑运算符两边的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对我来说似乎很特殊,因为尽管有类似的结构[Fidle],但它产生了不一致的结果
Logical OR
运算符不能以您想要的方式工作。
如果expr1可以转换为true,则返回它;否则,返回expr2。因此,当与布尔值一起使用时,如果任一操作数为true,则||返回true;如果两者都为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 ) { ... }
如果你想用一种干净的方法来检查一个变量是否等于许多其他变量中的任何一个,可以尝试使用这样的函数:
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'
做的事情。
作为替代解决方案,您可以使用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)) {
...
}
(a || b) == 'banana'
将始终为false,因为(a || b)
将返回一个不等于字符串的布尔值
更新:做了一些测试,(a || b)
总是返回第一个操作数(在本例中为a
),它是"apple",不等于"banana"。
||和&;只有当两个操作数都是布尔值或可以大小写为布尔值时,才会给出异常结果。
它的工作方式是a && b
和a || b
始终设置为其中一个变量的值。除非a
是false
,否则a && b
将始终设置为b
的值,在这种情况下,答案必须是false
。类似地,a || b
将被设置为a
的值,除非a
是false
,在这种情况下,它将被设置成b
的值。正如elclans所提到的,这是因为短路评估——第一个操作数可能决定结果,在这种情况下,查看第二个操作数没有意义。
当a
和b
都是字符串时,除非字符串长度为零,否则它们永远不会为false。因此,在您的情况下,a || b
将是"苹果",而a && b
将是"香蕉"。