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

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

118359 次浏览

查看:

你可以这样模仿它:

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

有……类:

if( foo ? !bar : bar ) {
...
}

或者更容易读:

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

为什么?不晓得。

因为javascript开发人员认为这是不必要的,因为它可以用其他已经实现的逻辑运算符来表示。

你也可以只用nand,就是这样,你可以从它得到所有其他可能的逻辑运算。

我个人认为它有历史原因,从基于c的语法语言驱动,据我所知,xor不存在或至少非常罕见。

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

如果你有两个布尔变量,你可以用:

if (a != b)

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

if (!a != !b)

这是相当晦涩的,当然值得评论。实际上,你甚至可以在这里使用按位的XOR操作符,尽管这对我来说太聪明了:

if (!a ^ !b)

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

var nb = 5^9 // = 12

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

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

但是这个结果的真值也可以用来判断一个“实”逻辑运算符返回的是真还是假。

这使得我们可以写出

if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {

if (image.hasAttribute('alt') || image.hasAttribute('title')) {

但是“逻辑”异或操作符(^^)总是必须对两个操作数求值。这使得它不同于其他“逻辑”操作符,后者只在必要时计算第二个操作数。我认为这就是Javascript中没有“逻辑”xor的原因,以避免混淆。


如果两个操作数都是假的,会发生什么?两者都可以归还。但只能退回一件。哪一个?第一个?还是第二个?我的直觉告诉我返回第一个,但通常“逻辑”操作符从左到右求值,并返回最后一个求值的值。或者一个包含这两个值的数组?

如果一个操作数为真,另一个操作数为假,xor应该返回真值。或者可能是一个包含真值的数组,以使它与前一种情况兼容?

最后,如果两个操作数都为真,会发生什么?你会期待一些虚假的东西。但没有虚假的结果。所以这个操作不应该返回任何东西。所以可能是undefined或..空数组?但空数组仍然为真。

采用数组方法,你最终会得到像if ((a ^^ b).length !== 1) {这样的条件。非常让人困惑。

将结果int转换为带有双重否定的保龄球如何?不是很漂亮,但是很紧凑。

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

试试这个简短易懂的

function xor(x,y){return true==(x!==y);}


function xnor(x,y){return !xor(x,y);}

这适用于任何数据类型

是的,只要做下面的事情。 假设您正在处理布尔值A和B,那么可以使用以下

在JavaScript中计算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     |
------------------------------------------

享受。

在上面的异或函数中,它将导致类似的结果,因为逻辑异或不完全是逻辑异或,这意味着它将导致"相等值为假""不同值为真",并考虑数据类型匹配。

这个异或函数将工作作为实际的异或或逻辑运算符,意味着根据传递的值是真相falsy,结果将为真或假。根据您的需要使用

function xor(x,y){return true==(!!x!==!!y);}


function xnor(x,y){return !xor(x,y);}

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

Boolean(a) !== Boolean(b)

没有逻辑异或(^^)的原因是与&&||它没有任何惰性逻辑优势。也就是左右两边表达式的状态都要求值。

在打印稿(+改变为数值):

value : number = (+false ^ +true)

所以:

value : boolean = (+false ^ +true) == 1

cond1 xor cond2等价于cond1 + cond 2 == 1:

证明如下:

let ops = [[false, false],[false, true], [true, false], [true, true]];


function xor(cond1, cond2){
return cond1 + cond2 == 1;
}


for(op of ops){
console.log(`${op[0]} xor ${op[1]} is ${xor(op[0], op[1])}`)
}

转换为布尔值,然后执行异或,比如-

!!a ^ !!b

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

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

注意,这个表达式的结果是数量是一个布尔值。

位异或也适用于非布尔值,但请记住,这是操作符,而不是逻辑操作符。使用非bool可能不会像你预想的那样:

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

这里有一个替代解决方案,与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!` );

我喜欢这个的原因是,它还回答了“这些变量中有多少是真实的?”,所以我通常会预先存储这个结果。

对于那些想要严格的布尔- true异或检查行为的人,只需执行:

if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.

如果你不关心计数,或者如果你关心最优性能:然后对强制为布尔值的值按位使用异或,用于真/假解决方案:

if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.

嘿,我找到了这个解决方案,在JavaScript和TypeScript上制作和XOR。

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
}

为了子孙后代的利益,也因为我发现这是一个很好的练习,您可以很容易地利用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中工作,通过强制显式的any:

const xor = (a: any, b: any) => !!((!!a as any) ^ (!!b as any))

Boolean的一行代码:

if (x ? !y : y) { do something cool }