Logical XOR in JavaScript

Navigation

Skip navigation.

Site search

Site navigation

What is XOR

XOR (exclusive OR) is a boolean operator, like && and ||, but with the following logic: It is successful if the expression on either side is true (like ||), but not if both sides are true (like !( x && y )).

Using the XOR logical operation in a conditional

Sometimes, in your JavaScript, you might want to do the following:

if( foo XOR bar ) {
  ...
}

Unfortunately, JavaScript does not have a logical XOR operator. It has a bitwise XOR operator ^ that can perform a bitwise comparison of two numbers, but this does not help when you want to obtain the result of an XOR of two expressions, that do not return a number.

The XOR operator can be simulated using this:

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

Or with one less operation (depending on the values of the foo and bar) using this:

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

Or using the ternary operator to make it even smaller:

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

With the exception of the ternary operator approach, this has a problem that if foo or bar are expressions, and not objects or literals, they will be evaluated twice. This means a slower script, and it may not be desirable to evaluate them twice, if they run functions or methods as part of the evaluation, when the code only expects them to be evaluated once. For this use, the XOR can be moved into its own function, so that the expressions are only evaluated once, and the function can be reused:

function myXOR(a,b) {
  return ( a || b ) && !( a && b );
}
...
if( myXOR( foo, bar ) ) {
  ...
}

If you only plan to use it once, you can even call the function inline (where you define an anonymous function, and immediately run it). Note that this syntax is very ugly, and you should only use it if you want your code to be very hard for anyone else (or even yourself) to debug:

if( (function (a,b) { return ( a || b ) && !( a && b ); })( foo, bar ) ) {
  ...
}

An alternative using the bitwise XOR operator

Since JavaScript has an XOR operator already, it would be nice to use it. It is possible, but the operator expects to be given numbers. So all you have to do is pass it different numbers based on the expressions that need to be compared. Make sure the numbers are the same as each other when they evaluate to true, and 0 when they evaluate to false. That way, when the expressions are evaluated, the returned value will be that number. For the sake of simplicity, 1 and 0 are a good choice. To create the appropriate numbers, simply use the ternary (?:) operator:

foo ? 1 : 0

This can then be used directly in the expression:

if( ( foo ? 1 : 0 ) ^ ( bar ? 1 : 0 ) ) {
  ...
}

This can also be used in function format, if the expressions are too complicated to be readable when written directly into the conditional:

function myXOR(a,b) {
  return ( a ? 1 : 0 ) ^ ( b ? 1 : 0 );
}
...
if( myXOR( foo, bar ) ) {
  ...
}

Or using ugly inline function syntax:

if( (function (a,b) { return ( a ? 1 : 0 ) ^ ( b ? 1 : 0 ); })( foo, bar ) ) {
  ...
}

The cleanest and best

The XOR operation can be described as "return true if the two boolean operands do not have the same value". So the actual response that is wanted is just this:

if( foo != bar ) {
  ...
}

That works if the two operands are both boolean true/false. However, to allow for other variable types (strings, expressions, etc.), it cannot work, since 'string' does not equal /regex/, even though the XOR operation would be expected to return false. So the operands need to be converted into boolean values first. This can be done like this:

foo ? true : false

However, it is easier and quicker to simply use the ! operator. This will give the opposite value - false instead of true, but as long as both operands get the same treatment, this will not affect the end result. So the simplest, cleanest version of the XOR operator, that works with any data types, including expressions, is this:

if( !foo != !bar ) {
  ...
}

Thanks to LTH for pointing this version out to me. What you choose to use, is up to you.

This site was created by Mark "Tarquin" Wilton-Jones.
Don't click this link unless you want to be banned from our site.