为什么 JavaScript 中没有逻辑异或?
为什么 JavaScript 中没有逻辑异或?
JavaScript 的祖先可以追溯到 C,而 C 没有逻辑 XOR 运算符。主要是因为它没有用。按位异或非常有用,但在我多年的编程生涯中,我从未需要逻辑异或。
如果您有两个布尔变量,您可以通过以下方式模拟 XOR:
if (a != b)
您可以使用两个任意变量将!
它们强制为布尔值,然后使用相同的技巧:
if (!a != !b)
不过,这相当晦涩难懂,当然值得评论。实际上,此时您甚至可以使用按位异或运算符,尽管这对我来说太聪明了:
if (!a ^ !b)
Javascript 有一个按位异或运算符:^
var nb = 5^9 // = 12
您可以将它与布尔值一起使用,它会将结果作为 0 或 1(您可以将其转换回布尔值,例如result = !!(op1 ^ op2)
)。但正如约翰所说,它相当于result = (op1 != op2)
,这更清楚。
Javascript 中没有真正的逻辑布尔运算符(尽管!
非常接近)。逻辑运算符只会将true
orfalse
作为操作数,并且只会返回true
or false
。
在 Javascript 中&&
,||
使用各种操作数并返回各种有趣的结果(无论你输入什么)。
此外,逻辑运算符应始终考虑两个操作数的值。
在 Javascript 中&&
并||
采取惰性快捷方式,在某些情况下不评估第二个操作数,从而忽略其副作用。这种行为不可能用逻辑异或重新创建。
a() && b()
a()
如果结果为假,则计算并返回结果。否则,它会评估b()
并返回结果。因此,如果两个结果都为真,则返回的结果为真,否则为假。
a() || b()
a()
如果结果为真,则计算并返回结果。否则,它会评估b()
并返回结果。因此,如果两个结果都为假,则返回的结果为假,否则为真。
所以一般的想法是先评估左操作数。仅在必要时评估正确的操作数。最后一个值是结果。这个结果可以是任何东西。对象、数字、字符串……随便!
这使得编写类似的东西成为可能
image = image || new Image(); // default to a new Image
或者
src = image && image.src; // only read out src if we have an image
但是这个结果的真值也可以用来决定一个“真正的”逻辑运算符是否会返回真或假。
这使得编写类似的东西成为可能
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
或者
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
但是“逻辑”异或运算符 ( ^^
) 将始终必须评估两个操作数。这使它与其他“逻辑”运算符不同,后者仅在必要时评估第二个操作数。我认为这就是 Javascript 中没有“逻辑”xor 以避免混淆的原因。
那么如果两个操作数都是假的,会发生什么?两者都可以退货。但只能退货。哪一个?第一个?还是第二个?我的直觉告诉我返回第一个但通常是“逻辑”运算符从左到右求值并返回最后一个求值值。或者可能是一个包含两个值的数组?
如果一个操作数为真而另一个操作数为假,则异或应返回真值。或者也许是一个包含真实数组的数组,以使其与前一种情况兼容?
最后,如果两个操作数都是真值,会发生什么?你会期待一些虚假的东西。但是没有错误的结果。所以操作不应该返回任何东西。所以也许undefined
还是..一个空数组?但是空数组仍然是真实的。
采用数组方法,您最终会遇到类似if ((a ^^ b).length !== 1) {
. 很混乱。
两个布尔值的异或只是它们是否不同,因此:
Boolean(a) !== Boolean(b)
将值转换为布尔形式,然后按位异或:
Boolean(a) ^ Boolean(b) // === 0 | 1
请注意,此表达式的结果是数字而不是布尔值。
按位异或也适用于非布尔值,但请记住,这是按位运算符,而不是逻辑运算符。使用非布尔值可能不会像您最初期望的那样进行:
(5 ^ 3) === 6 // true