为什么 JavaScript 中没有逻辑异或?

IT技术 javascript xor logical-operators
2021-02-24 23:29:29

为什么 JavaScript 中没有逻辑异或?

6个回答

JavaScript 的祖先可以追溯到 C,而 C 没有逻辑 XOR 运算符。主要是因为它没有用。按位异或非常有用,但在我多年的编程生涯中,我从未需要逻辑异或。

如果您有两个布尔变量,您可以通过以下方式模拟 XOR:

if (a != b)

您可以使用两个任意变量将!它们强制为布尔值,然后使用相同的技巧:

if (!a != !b)

不过,这相当晦涩难懂,当然值得评论。实际上,此时您甚至可以使用按位异或运算符,尽管这对我来说太聪明了:

if (!a ^ !b)
只要你已经有两个布尔变量,a并且b,XOR 确实是多余的。但是当人们已经有了布尔变量时,他们通常不需要布尔运算。你永远不会做const a = foo == bar; if (a == true) { console.log("foo=bar"); }布尔运算的重点是允许简单的内联测试,由编译器优化,没有定义无关变量的开销。
2021-05-05 23:29:29
唯一的问题!=是你不能做同样的事情a ^= b,因为a !== b只是严格的不等式运算符。
2021-05-11 23:29:29

Javascript 有一个按位异或运算符:^

var nb = 5^9 // = 12

您可以将它与布尔值一起使用,它会将结果作为 0 或 1(您可以将其转换回布尔值,例如result = !!(op1 ^ op2))。但正如约翰所说,它相当于result = (op1 != op2),这更清楚。

您可以将其用作逻辑异或。true^true为 0,false^true为 1。
2021-04-20 23:29:29
@Pikrass你可以使用它作为一个逻辑运算符针对布尔值,而不是其他类型。||and&&可以用作非布尔值的逻辑运算符(例如5 || 7返回一个真值,"bob" && null返回一个假值)但^不能。例如,5 ^ 7等于 2,这是真的。
2021-04-26 23:29:29
@Pikrass 您永远不应该将它用作布尔值的逻辑运算符,因为实现取决于操作系统。我正在使用某种a ^= true来切换布尔值,但它在某些机器(如手机)上失败了。
2021-05-03 23:29:29
@cronvel 当然,只是有时,您尝试缩短超长路径,例如myObj.collection[index].someImportantFlag = !myObj.collection[index].someImportantFlag使用^= true. 我再也不会被诱惑了:)
2021-05-08 23:29:29
@Pikrass 但遗憾的是(true ^ false) !== true,这让需要实际布尔值的库变得烦人
2021-05-10 23:29:29

Javascript 中没有真正的逻辑布尔运算符(尽管!非常接近)。逻辑运算符只会将trueorfalse作为操作数,并且只会返回trueor 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) {. 很混乱。

任何语言中的 XOR/^^ 总是必须评估两个操作数,因为它总是依赖于两者。AND/&& 也是如此,因为所有操作数都必须为真(在 JS 中为真)返回传递。例外是 OR/|| 因为它必须只评估操作数,直到找到一个真值。如果 OR 列表中的第一个操作数为真,则不会评估其他操作数。
2021-04-16 23:29:29
@DDS 感谢您纠正答案。我很困惑为什么我自己没有注意到它。也许这在一定程度上解释了珀西的困惑。
2021-04-16 23:29:29
我的编辑被拒绝了,之后@matts 完全按照我修复它的方式重新编辑了它,所以我错过了我的(可怜的)2 分。3 个人拒绝了它,我对他们使用的标准感到困惑。Thx 垫子。
2021-04-20 23:29:29
不过,您确实提出了一个很好的观点,即 JS 中的 XOR 必须打破 AND 和 OR 规定的约定。它实际上必须返回一个正确的布尔值,而不是两个操作数之一。其他任何事情都可能导致混乱/复杂性。
2021-04-25 23:29:29
如果第一个操作数为假,@Percy AND/&& 不会评估第二个操作数。它只计算操作数,直到找到一个假值。
2021-04-28 23:29:29

两个布尔值的异或只是它们是否不同,因此:

Boolean(a) !== Boolean(b)
我不得不使用这个解决方案,因为当你尝试使用^布尔值时,TypeScript 会抱怨
2021-05-09 23:29:29

将值转换为布尔形式,然后按位异或

Boolean(a) ^ Boolean(b) // === 0 | 1

请注意,此表达式的结果是数字不是布尔值。

按位异或也适用于非布尔值,但请记住,这是按位运算符,而不是逻辑运算符。使用非布尔值可能不会像您最初期望的那样进行:

(5 ^ 3) === 6 // true