为什么JavaScript中没有逻辑xor?
答案 0 :(得分:323)
JavaScript将其祖先追溯到C,而C没有逻辑XOR运算符。主要是因为它没用。 Bitwise XOR非常有用,但在我多年的编程中,我从未需要逻辑XOR。
如果您有两个布尔变量,则可以使用以下方式模拟XOR:
if (a != b)
使用两个任意变量,您可以使用!
将它们强制转换为布尔值,然后使用相同的技巧:
if (!a != !b)
虽然这很晦涩但肯定值得评论。实际上,你甚至可以在这一点上使用按位XOR运算符,尽管这对我来说太聪明了:
if (!a ^ !b)
答案 1 :(得分:72)
Javascript有一个按位XOR运算符:^
var nb = 5^9 // = 12
您可以将它与布尔值一起使用,它会将结果显示为0或1(您可以将其转换回布尔值,例如result = !!(op1 ^ op2)
)。但正如约翰所说,它相当于result = (op1 != op2)
,这更清楚。
答案 2 :(得分:27)
Javascript中没有真正的逻辑布尔运算符(尽管!
非常接近)。逻辑运算符只能将true
或false
作为操作数,并且只返回true
或false
。
在Javascript &&
和||
中获取所有类型的操作数并返回各种有趣的结果(无论你输入什么内容)。
逻辑运算符也应始终考虑两个操作数的值。
在Javascript &&
和||
中使用懒惰的快捷方式并在某些情况下执行不评估第二个操作数,从而忽略其副作用。使用逻辑xor无法重新创建此行为。
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
但是这个结果的真值也可以用来判断“真正的”逻辑运算符是返回true还是false。
这样就可以编写像
这样的内容if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
或
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
但是“逻辑”xor运算符(^^
)总是必须评估两个操作数。这使得它与仅在必要时评估第二操作数的其他“逻辑”运算符不同。我认为这就是Javascript中没有“逻辑”xor的原因,以避免混淆。
那么如果两个操作数都是假的会发生什么呢?两者都可以归还。但只有一个可以返回。哪一个?第一个?还是第二个?我的直觉告诉我返回第一个但通常是“逻辑”的运算符从左到右评估并返回最后一个评估值。或者可能是包含两个值的数组?
如果一个操作数是真实的而另一个操作数是假的,那么xor应该返回真正的操作数。或者也许是一个包含真实数组的数组,以使其与之前的情况兼容?
最后,如果两个操作数都是真的会发生什么?你会期待一些虚假的东西。但没有虚假的结果。所以操作不应该返回任何东西。也许undefined
或..一个空数组?但是一个空阵列仍然很简洁。
采用数组方法,最终会遇到像if ((a ^^ b).length !== 1) {
这样的条件。非常混乱。
答案 3 :(得分:10)
两个布尔的异或只是它们是否不同,因此:
Boolean(a) !== Boolean(b)
答案 4 :(得分:9)
有......有点:
if( foo ? !bar : bar ) {
...
}
或更容易阅读:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
为什么呢?不知道。
因为javascript开发人员认为它是不必要的,因为它可以由其他已经实现的逻辑运算符表示。
你也可以和nand一起使用,就这样,你可以从中得到其他可能的逻辑操作。
我个人认为它有历史原因驱使用基于c语言的语言,据我所知,xor不存在或者至少非常罕见。
答案 5 :(得分:7)
是的,请执行以下操作。 假设您正在处理布尔A和B,那么可以使用以下
在JavaScript中计算A XOR B值var xor1 = !(a === b);
前一行也等同于以下
var xor2 = (!a !== !b);
就个人而言,我更喜欢xor1,因为我必须输入更少的字符。我相信xor1也更快。它只是执行两次计算。 xor2正在进行三次计算。
视觉解释...阅读下表(其中0代表假,1代表真),并比较第3和第5列。
!(A === B):
| A | B | A XOR B | A === B | !(A === B) |
------------------------------------------
| 0 | 0 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 1 | 0 |
------------------------------------------
享受。
答案 6 :(得分:4)
如何用双重否定将结果 int 转换为 bool ?不是那么漂亮,但非常紧凑。
var state1 = false,
state2 = true;
var A = state1 ^ state2; // will become 1
var B = !!(state1 ^ state2); // will become true
console.log(A);
console.log(B);
答案 7 :(得分:4)
答案 8 :(得分:2)
在上面的xor函数中,它将导致 SIMILAR 结果,因为逻辑xor不完全是逻辑xor,意味着它将导致“false表示相等的值”和“对于考虑了数据类型匹配的不同值“,则为true。
此xor函数将作为实际xor或逻辑运算符,表示根据传递的值 truthy 或 falsy 。根据您的需要使用
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
答案 9 :(得分:2)
转换为布尔值,然后执行xor-
!!a ^ !!b
答案 10 :(得分:2)
将值转换为布尔形式,然后进行按位XOR。 还将对非布尔值也有帮助。
Boolean(a) ^ Boolean(b)
答案 11 :(得分:2)
一个布尔值布尔值:
if (x ? !y : y) { do something cool }
答案 12 :(得分:1)
您使用import React from 'react';
import Test from './Test';
import { mount } from 'enzyme';
it('renders correctly', () => {
const wrapper = mount(<Test />); // renders successfully
...
});
等同于cond1 xor cond2
的事实:
cond1 + cond 2 == 1
答案 13 :(得分:0)
没有逻辑XOR(^^)的原因是因为&amp;&amp;和||它没有给出任何惰性逻辑优势。这就是必须评估左右两个表达式的状态。
答案 14 :(得分:0)
在打字稿中(“ +”更改为数值):
value : number = (+false ^ +true)
所以:
value : boolean = (+false ^ +true) == 1
答案 15 :(得分:0)
这是另一种解决方案,可处理2个以上变量并提供计数作为奖励。
这是一种更通用的解决方案,可以对任何真假值进行逻辑XOR仿真,就像在标准IF语句中使用运算符一样:
const v1 = true;
const v2 = -1; // truthy (warning, as always)
const v3 = ""; // falsy
const v4 = 783; // truthy
const v5 = false;
if( ( !!v1 + !!v2 + !!v3 + !!v4 + !!v5 ) === 1 )
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is TRUE!` );
else
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is FALSE!` );
之所以喜欢,是因为它还会回答“这些变量中有多少是真实的?”,因此我通常会预先存储该结果。
对于那些想要严格的布尔-真xor检查行为的人,只需执行以下操作即可:
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.
如果您不关心计数,或者您不关心最佳性能:,那么只需对逼迫为布尔值的值使用按位异或运算即可,以得出真实/错误的解决方案:
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.
答案 16 :(得分:0)
嘿,我找到了这个解决方案,可以在JavaScript和TypeScript上进行异或。
if( +!!a ^ +!!b )
{
//This happens only when a is true and b is false or a is false and b is true.
}
else
{
//This happens only when a is true and b is true or a is false and b is false
}
答案 17 :(得分:0)
为了后代的缘故,并且因为我发现这是一个很好的练习,所以您可以很容易地利用XOR运算符利用真实性来进行强制。像选择的答案一样,它可能有点聪明。
const xor = (a, b) => !!(!!a ^ !!b)
console.log(undefined ^ {}) // Returns 0, bitwise can't be done here.
console.log(xor(undefined, {})) // Returns true, because {} is truthy and undefined is falsy
console.log(0 ^ 1) // Works naturally, returns 1
console.log(xor(0, 1)) // Also works, returns true
console.log(true ^ false) // Again, returns true
console.log(xor(true, false)) // And again, returns true...
为了娱乐,这应该在TypeScript中起作用,方法是强制使用显式的任意值:
const xor = (a: any, b: any) => !!((!!a as any) ^ (!!b as any))
答案 18 :(得分:-2)
尝试这个简短易懂的
function xor(x,y){return true==(x!==y);}
function xnor(x,y){return !xor(x,y);}
这适用于任何数据类型