Why is there no logical XOR
in JavaScript?

- 13,617
- 16
- 88
- 129

- 14,980
- 18
- 49
- 57
20 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)

- 349,597
- 67
- 533
- 578
-
The only problem with `!=` is that you can't do the same as `a ^= b`, because `a !== b` is just the [strict inequality](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Nonidentity) operator. – mcpiroman Jan 02 '20 at 19:34
-
3As long as you already have two boolean variables, `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. – Bogdan Stăncescu Dec 26 '20 at 19:30
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.

- 6,819
- 1
- 28
- 24
-
77You can use it as a logical xor. `true^true` is 0, and `false^true` is 1. – Pik' Dec 27 '10 at 17:29
-
17@Pikrass You can use it as a logical operator *on booleans*, but not on other types. `||` 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. – Mark Amery Sep 27 '14 at 22:11
-
13@Pikrass But sadly, `(true ^ false) !== true`, which makes it annoying with libraries that require actual booleans – Izkata Oct 01 '14 at 14:59
-
4@Pikrass You should never use it as a logical operator on boolean because implementation is OS dependant. I was using some kind of `a ^= true` to toggle booleans and it fails on some machines such as phones. – Masadow Jun 05 '15 at 15:14
-
@Masadow lol, if you want to negate a boolean, consider using `a = !a`. I mean: it's the *NOT* operator, man! That's just like bashing a nail with a screwdriver instead of using the hammer. – cronvel Oct 22 '16 at 14:26
-
2@cronvel Sure, it's just that sometimes, you try to shorten super long path such as `myObj.collection[index].someImportantFlag = !myObj.collection[index].someImportantFlag` so it was more convenient to write it with `^= true`. I will never be tempted again :) – Masadow Oct 26 '16 at 09:11
-
using cap `^` operator we can perfotm multiple task in javascript if you use with `Boolean` it is perform `XOR` operation and if you use with integers it is perform `bitwise` operation. – Umair Ahmed Oct 29 '16 at 07:25
-
@Masadow `^`'s behavior is not "OS-dependent," even when used with non-numerical values. It's fully defined in ECMA262: the operands are first converted to primitives and then to numbers following [section 13.15.3](https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator). – ZachB Apr 21 '21 at 23:13
-
@ZachB Back in 2016, ECMA262 did not exist... So yeah, it was OS dependant and the result would differ for different unix versions (from what I witnessed at least). It might not probably be the case anymore if you use a system that properly implement ECMA262 – Masadow Apr 23 '21 at 09:37
-
1@Masadow The first edition of ECMA-262 was published in 1997. `BitwiseXORExpression` has nearly identical semantics in [that edition](https://www.ecma-international.org/wp-content/uploads/ECMA-262_1st_edition_june_1997.pdf) (section 11.10) as in the latest edition. Perhaps you were using a flawed ECMAScript engine... – ZachB Apr 23 '21 at 17:27
The XOR of two booleans is simply whether they are different, therefore:
Boolean(a) !== Boolean(b)

- 4,184
- 38
- 37
-
2I had to use this solution because TypeScript complains when you try to use `^` with booleans. – Nathan Arthur Apr 28 '21 at 23:02
There 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.

- 2,603
- 26
- 25
-
XOR/^^ in any language will always have to evaluate both operands since it is always dependent on both. The same goes for AND/&&, since all operands must be true (truthy in JS) return pass. The exception is OR/|| since it must only evaluate operands until it finds a truthy value. If the first operand in an OR list is truthy, none of the others will be evaluated. – Percy Jun 03 '12 at 00:29
-
You do make a good point, though, that XOR in JS would have to break the convention set forth by AND and OR. It would actually have to return a proper boolean value rather than one of the two operands. Anything else could cause confusion/complexity. – Percy Jun 03 '12 at 00:30
-
9@Percy AND/&& doesn't evaluate the second operand if the first one is false. It only evaluates operands until it finds a falsy value. – Robert Jun 04 '12 at 08:16
-
@DDS Thanks for rectifying the answer. I'm puzzled as to why I didn't notice it myself. Maybe this explains Percy's confusion to some extent. – Robert Jul 15 '14 at 16:32
-
My edit was rejected, after which @matts re-edited it exactly the way I fixed it, so I missed my (measely) 2 points. 3 people rejected it and I'm baffled what they used as their criteria. Thx matts. – DDS Jul 18 '14 at 00:36
-
@DDS Whoops, I didn't mean to deprive you of your points like that. (No points for me either since I'm over 2k rep.) Didn't know if you'd try to make the edit again and I wanted to make sure the truth got out there :P Thanks for being a thorough reader and fixing it in the first place! – matts Jul 18 '14 at 04:54
-
@matts I think you were absolutely right to reimplement the edit. I do this frequently when I see good edit suggestions perversely rejected - but I like to link back to the original suggested edit from my edit message when doing so. This at leasts gives the suggester some credit and - if they return to the post later - the comfort of knowing that *somebody* appreciated their work and recognised that they were the victim of a foolish injustice at the hands of the review queue. – Mark Amery Sep 27 '14 at 22:05
-
Turning this into a concrete solution, would you say `const xor = (a, b) => (a && b ? undefined: (a ? a : b))` or `const xor = (a, b) => (a && b ? undefined: (b ? b : a))` does the trick? – BCDeWitt Jul 06 '18 at 21:22
-
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

- 2,590
- 1
- 18
- 31

- 124
- 1
- 2
- 10
-
8Note that `!!a ^ !!b` is equivalent to `!a ^ !b`. Arguments could be made as to which is easier to read. – tschwab Nov 08 '19 at 19:45
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.

- 29,118
- 24
- 122
- 168
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.

- 5,377
- 1
- 22
- 43

- 3,229
- 29
- 32
-
6
-
This answer won't work for all data types (like Premchandra's answer). e.g. `!(2 === 3)` is `true`, but `2` and `3` are **truthy** so `2 XOR 3` should be `false`. – Mariano Desanze Feb 02 '16 at 21:38
-
3If you had read my message more carefully, you would have noticed that I wrote "Assuming that you are dealing with booleans A and B ...". – asiby Feb 03 '16 at 01:50
Check out:
You can mimic it something like this:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}

- 377,238
- 77
- 533
- 578
-
3Hey if they added a logical XOR operator to JavaScript it would make the code example look much cleaner. – Danyal Aytekin Jul 25 '11 at 12:15
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);

- 4,433
- 2
- 26
- 37

- 3,756
- 2
- 20
- 26
-
This will fail if the operands aren't already boolean. Much better idea is `B = ((!state1)!==(!state2))` – Doin Dec 14 '16 at 16:32
-
True, but you can always negate the operands to cast them, like you did if you are not sure of the types: ```B =!!(!state1 ^ !state2);``` Also, why so many parenthesis? ```B = !state1 !== !state2;``` Or you can even drop the negation: ```B = state1 !== state2;``` – Lajos Mészáros Dec 14 '16 at 16:44
-
Parenthesis are for clarity, and also so I don't have to check the docs on operator precedence when writing code! ;-) Your last expression suffers from my previous complaint: It fails if the operands aren't boolean. But if you're sure they are, then it's definitely the simplest and fastest "logical xor" expression. – Doin Dec 16 '16 at 03:37
-
If by last expression you mean ```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. – Lajos Mészáros Dec 16 '16 at 12:01
-
By the way, I prefer extra spaces over parenthesis for readability. – Lajos Mészáros Dec 16 '16 at 12:03
-
1The result of both `!==` 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. – Doin Dec 17 '16 at 12:50
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))

- 543
- 3
- 7
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);}

- 14,156
- 4
- 31
- 37
-
-
@daniel1426 not quite. It is the same as `(!!x) === (!!y)`. The difference is a cast to boolean. `'' === 0` is false, while `xnor('', 0)` is true. – tschwab Nov 08 '19 at 19:50
The reason there is no logical XOR (^^) is because unlike && and || it does not give any lazy-logic advantage. That is the state of both expressions on the right and left have to be evaluated.

- 21
- 1
In Typescript (The + changes to numeric value):
value : number = (+false ^ +true)
So:
value : boolean = (+false ^ +true) == 1

- 9,845
- 3
- 58
- 67
-
@Sheraff in normal javascript, `!!(false ^ true)` works fine with booleans. In typescript, + is required to make it valid `!!(+false ^ +true)`. – pfg Feb 23 '20 at 04:06
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])}`)
}

- 5,104
- 2
- 19
- 31
-
For this proof to be meaningful in a real-world context, I would suggest modifying the values to accept any truthy/falsy value, rather than booleans alone: `function xor(cond1, cond2){ return !!cond1 + !!cond2 === 1 }` – Chris Perry Oct 08 '21 at 17:40
-
@ChrisPerry I understand your suggestion. But my answer is about the *concept* of XOR, which tackles Boolean entities. With truthy comparisons you end up mixing notions that shouldn't be mixed in my opinion. It is a personal choice and I prefer limiting the scope of my answer to Booleans. – madjaoue Oct 13 '21 at 14:11
-
Isn't the whole point of JavaScript that truthy notations *should* be mixed? – Chris Perry Oct 18 '21 at 22:31
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.

- 1,984
- 13
- 15
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');

- 26,865
- 29
- 124
- 202
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
}
-
while the solution works, it is definitely the least readable of all answers with all those cryptic symbols. I would rather see the statement written in the comment turned into code. – Lajos Mészáros Apr 22 '21 at 11:35
-
This solution is a little overcomplicated, without any gain for it. The unary pluses are just redundant and unnecessary, since a single `!` 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. – zcoop98 Jun 16 '21 at 23:49
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

- 14,156
- 4
- 31
- 37
-
4This doesn't work for all data types. As with a logical type coercing operator, I would expect "foo" xor "bar" to be false, because both are truthy. That is currently not the case with your function. Generally, doing `true == someboolean` is not necessary, so really, what you've done is wrapping the strict not-equals into a function. – Gijs Jul 31 '13 at 15:27
-
Hi GiJs, I agree your argument, "foo" and "bar" are truthy values. But I write the function keeping in mind that it will result similar output as xor does (un-equal values results true, equal values results false) not for truthy/falsy value only. And I found more usage in such scenario. But I am writing true logical xor in another answer below. – Premchandra Singh Aug 08 '13 at 07:47