为什么JavaScript中没有逻辑xor?

时间:2010-12-27 17:15:10

标签: javascript xor logical-operators

为什么JavaScript中没有逻辑xor?

19 个答案:

答案 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中没有真正的逻辑布尔运算符(尽管!非常接近)。逻辑运算符只能将truefalse作为操作数,并且只返回truefalse

在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)

退房:

你可以模仿这样的东西:

if( ( foo && !bar ) || ( !foo && bar ) ) {
  ...
}

答案 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);}

这适用于任何数据类型