Why is there no logical XOR in JavaScript?
22 Answers
JavaScript traces its ancestry back to C, and C does not have a logical XOR operator. Mainly because it's not useful. Bitwise XOR is extremely useful, but in all my years of programming I have never needed a logical XOR.
If you have two boolean variables you can mimic XOR with:
if (a != b) With two arbitrary variables you could use ! to coerce them to boolean values and then use the same trick:
if (!a != !b) That's pretty obscure though and would certainly deserve a comment. Indeed, you could even use the bitwise XOR operator at this point, though this would be far too clever for my taste:
if (!a ^ !b) 5 Comments
!= is that you can't do the same as a ^= b, because a !== b is just the strict inequality operator.a and b, XOR is indeed redundant. But people don't generally need boolean operations when they already have boolean variables. You never do const a = foo == bar; if (a == true) { console.log("foo=bar"); } The very point of boolean operations is allowing for simple inline tests, optimized by the compiler, without the overhead of defining extraneous variables.data.filter(e => (e.something== reference) ^ invertmatch). xor makes this condition much easier to write (though it deserves a comment). At least when working with boolean values, bitwise xor can be used just fine.Javascript has a bitwise XOR operator : ^
var nb = 5^9 // = 12 You can use it with booleans and it will give the result as a 0 or 1 (which you can convert back to boolean, e.g. result = !!(op1 ^ op2)). But as John said, it's equivalent to result = (op1 != op2), which is clearer.
10 Comments
true^true is 0, and false^true is 1.|| and && can be used as logical operators on non-booleans (e.g. 5 || 7 returns a truthy value, "bob" && null returns a falsey value) but ^ cannot. For example, 5 ^ 7 equals 2, which is truthy.(true ^ false) !== true, which makes it annoying with libraries that require actual booleansa ^= true to toggle booleans and it fails on some machines such as phones.myObj.collection[index].someImportantFlag = !myObj.collection[index].someImportantFlag so it was more convenient to write it with ^= true. I will never be tempted again :)The XOR of two booleans is simply whether they are different, therefore:
Boolean(a) !== Boolean(b) 3 Comments
^ with booleans.a !== bThere are no real logical boolean operators in Javascript (although ! comes quite close). A logical operator would only take true or false as operands and would only return true or false.
In Javascript && and || take all kinds of operands and return all kinds of funny results (whatever you feed into them).
Also a logical operator should always take the values of both operands into account.
In Javascript && and || take a lazy shortcut and do not evaluate the second operand in certain cases and thereby neglect its side effects. This behavior is impossible to recreate with a logical xor.
a() && b() evaluates a() and returns the result if it's falsy. Otherwise it evaluates b() and returns the result. Therefore the returned result is truthy if both results are truthy, and falsy otherwise.
a() || b() evaluates a() and returns the result if it's truthy. Otherwise it evaluates b() and returns the result. Therefore the returned result is falsy if both results are falsy, and truthy otherwise.
So the general idea is to evaluate the left operand first. The right operand only gets evaluated if necessary. And the last value is the result. This result can be anything. Objects, numbers, strings .. whatever!
This makes it possible to write things like
image = image || new Image(); // default to a new Image or
src = image && image.src; // only read out src if we have an image But the truth value of this result can also be used to decide if a "real" logical operator would have returned true or false.
This makes it possible to write things like
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) { or
if (image.hasAttribute('alt') || image.hasAttribute('title')) { But a "logical" xor operator (^^) would always have to evaluate both operands. This makes it different to the other "logical" operators which evaluate the second operand only if necessary. I think this is why there is no "logical" xor in Javascript, to avoid confusion.
So what should happen if both operands are falsy? Both could be returned. But only one can be returned. Which one? The first one? Or the second one? My intuition tells me to return the first but usually "logical" operators evaluate from left to right and return the last evaluated value. Or maybe an array containing both values?
And if one operand is truthy and the other operand is falsy, an xor should return the truthy one. Or maybe an array containing the truthy one, to make it compatible with the previous case?
And finally, what should happen if both operands are truthy? You would expect something falsy. But there are no falsy results. So the operation shouldn't return anything. So maybe undefined or .. an empty array? But an empty array is still truthy.
Taking the array approach you would end up with conditions like if ((a ^^ b).length !== 1) {. Very confusing.
9 Comments
Convert values into Boolean form and then take bitwise XOR:
Boolean(a) ^ Boolean(b) // === 0 | 1 Note that the result of this expression is a number and not a Boolean.
Bitwise XOR also works with non-Boolean values, but remember that this is a bitwise operator, and not a logical one. Using non-bools may not go as you first expect:
(5 ^ 3) === 6 // true 1 Comment
Covert to boolean and then perform xor like -
!!a ^ !!b 1 Comment
!!a ^ !!b is equivalent to !a ^ !b. Arguments could be made as to which is easier to read.there is... sort of:
if( foo ? !bar : bar ) { ... } or easier to read:
if( ( foo && !bar ) || ( !foo && bar ) ) { ... } why? dunno.
because javascript developers thought it would be unnecessary as it can be expressed by other, already implemented, logical operators.
you could as well just have gon with nand and thats it, you can impress every other possible logical operation from that.
i personally think it has historical reasons that drive from c-based syntax languages, where to my knowledge xor is not present or at least exremely uncommon.
Yes, Just do the following. Assuming that you are dealing with booleans A and B, then A XOR B value can be calculated in JavaScript using the following
var xor1 = a !== b; The previous line is also equivalent to the following
var xor2 = (!a !== !b); Personally, I prefer xor1 since I have to type less characters. I believe that xor1 is also faster too. It's just performing two calculations. xor2 is performing three calculations.
Visual Explanation ... Read the table bellow (where 0 stands for false and 1 stands for true) and compare the 3rd and 5th columns.
!(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 | ------------------------------------------ Enjoy.
3 Comments
var xor1 = !(a === b); is the same as var xor1 = a !== b;!(2 === 3) is true, but 2 and 3 are truthy so 2 XOR 3 should be false.Check out:
You can mimic it something like this:
if( ( foo && !bar ) || ( !foo && bar ) ) { ... } 1 Comment
For posterity's sake, and because I found this to be a good exercise, you can leverage truthiness with the XOR operator quite easily to coerce. Like the chosen answer, it's probably a bit too clever.
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... And for fun, this should work in TypeScript, by forcing explicit any:
const xor = (a: any, b: any) => !!((!!a as any) ^ (!!b as any)) 1 Comment
How about transforming the result int to a bool with double negation? Not so pretty, but really compact.
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); 6 Comments
B = ((!state1)!==(!state2))B =!!(!state1 ^ !state2); Also, why so many parenthesis? B = !state1 !== !state2; Or you can even drop the negation: B = state1 !== state2;state1 !== state2, then you don't need to do any casting there, since !== is a logical operator, not a bitwise. 12 !== 4 is true 'xy' !== true is also true. If you would use != instead of !==, then you would have to do casting.!== and != is always boolean... not sure what the distinction you're making there is supposed to be, that's absolutely not the problem. The problem is that the XOR operator we want is really the expression (Boolean(state1) !== Boolean(state2)). For booleans, "xy", 12, 4 and true are all truthy values, and should convert to true. so ("xy" XOR true) should be false, but ("xy" !== true) is instead true, as you point out. So !== or != are (both) equivalent to "logical XOR" if and only if you convert their arguments to booleans before applying.One liner for Boolean:
if (x ? !y : y) { do something cool } 1 Comment
In above xor function it will result SIMILAR result as logical xor does not exactly logical xor, means it will result "false for equal values" and "true for different values" with data type matching in consideration.
This xor function will work as actual xor or logical operator, means it will result true or false according to the passing values are truthy or falsy. Use according to your needs
function xor(x,y){return true==(!!x!==!!y);} function xnor(x,y){return !xor(x,y);} 2 Comments
(!!x) === (!!y). The difference is a cast to boolean. '' === 0 is false, while xnor('', 0) is true.In Typescript (The + changes to numeric value):
value : number = (+false ^ +true) So:
value : boolean = (+false ^ +true) == 1 1 Comment
!!(false ^ true) works fine with booleans. In typescript, + is required to make it valid !!(+false ^ +true).cond1 xor cond2 is equivalent to cond1 + cond 2 == 1:
Here's the proof :
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])}`) } 3 Comments
function xor(cond1, cond2){ return !!cond1 + !!cond2 === 1 }Lots of discussion on why this is not available, and other methods. What I'd like to focus on is how to make this approachable and scalable so that it's reasonably easy to understand/maintain, and easy to extend for a collection (array) of values; to that end:
[true, false].filter(x => x).length === 1; // true, only 1 truthy [false, true, false].filter(x => x).length === 1; // true, only 1 truthy [true, false, true].filter(x => x).length === 1; // false, 2+ truthy Leverages the Array's filter and length members and easily fits inline. Or, can be made reusable in a function, plus sample use:
function xor(array) { return (array ?? []).filter(x => x).length === 1; } xor([true, false]); // true, only 1 truthy xor([false, true, false]); // true, only 1 truthy xor([true, false, true]); // false, 2+ truthy 1 Comment
=== 1 test should check for any odd number instead.)This simple solution could help anyone having the same issue.
It returns true when only one of the passed-in arguments is truthy. You can use as many arguments as needed.
function xOr(...items) { let trueCount = 0 items.forEach(item => { if (!!item) trueCount++ }) return trueCount === 1 } console.log('false xor false =>', xOr(false, false)); console.log('false xor true \t =>', xOr(false, true)); console.log('true xor false \t =>', xOr(true, false)); console.log('true xor true \t =>', xOr(true, true)); This solution iterate through all items regardless. For better performance, an improved loop can be used so the function return false as soon as the collection is known to contain more than one truthy value.
// Coming soon Here's an alternate solution that works with 2+ variables and provides count as bonus.
Here's a more general solution to simulate logical XOR for any truthy/falsey values, just as if you'd have the operator in standard IF statements:
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!` ); The reason I like this, is because it also answers "How many of these variables are truthy?", so I usually pre-store that result.
And for those who want strict boolean-TRUE xor check behaviour, just do:
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 ) // etc. If you don't care about the count, or if you care about optimal performance: then just use the bitwise xor on values coerced to boolean, for the truthy/falsy solution:
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 ) // etc. Comments
Most of the proposed methods here are hard to read and understand. Instead of writing some cryptic and magical comparisons or trying to comment them, just define a reusable function that is self-explanatory:
function either(a: boolean, b: boolean): boolean { return (a !== b); } Or a more universal one:
function either(a: any, b: any): boolean { return Boolean(a) !== Boolean(b); } Then you can use it like this:
assert(either(one, another), 'Either one or another, not both'); Comments
Hey I found this solution, to make and XOR on JavaScript and 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 } 2 Comments
! already converts the operand to a bool. This means that all the + does is convert true or false into 1 or 0, both of which have identical outcomes in this context. Also worth noting that !!a ^ !!b is equivalent to !a ^ !b too.Try this short and easy to understand one
function xor(x,y){return true==(x!==y);} function xnor(x,y){return !xor(x,y);} This will work for any data type
2 Comments
true == someboolean is not necessary, so really, what you've done is wrapping the strict not-equals into a function.