OscuridadLuzA
¿Por qué no hay lógica? XOR
en JavaScript?
Juan Kugelman
JavaScript rastrea su ascendencia hasta C, y C no tiene un operador XOR lógico. Principalmente porque no es útil. Bitwise XOR es extremadamente útil, pero en todos mis años de programación nunca he necesitado un XOR lógico.
Si tiene dos variables booleanas, puede imitar XOR con:
if (a != b)
Con dos variables arbitrarias podrías usar !
para forzarlos a valores booleanos y luego usar el mismo truco:
if (!a != !b)
Sin embargo, eso es bastante oscuro y ciertamente merecería un comentario. De hecho, incluso podría usar el operador XOR bit a bit en este punto, aunque esto sería demasiado inteligente para mi gusto:
if (!a ^ !b)
-
El único problema con
!=
es que no puedes hacer lo mismo quea ^= b
porquea !== b
es solo el desigualdad estricta operador.– mcpiroman
2 de enero de 2020 a las 19:34
-
Siempre que ya tenga dos variables booleanas,
a
yb
, XOR es de hecho redundante. Pero las personas generalmente no necesitan operaciones booleanas cuando ya tienen variables booleanas. nunca lo hacesconst a = foo == bar; if (a == true) { console.log("foo=bar"); }
El objetivo de las operaciones booleanas es permitir pruebas sencillas en línea, optimizadas por el compilador, sin la sobrecarga de definir variables extrañas.– Bogdan Stăncescu
26 dic 2020 a las 19:30
Pik’
Javascript tiene un operador XOR bit a bit: ^
var nb = 5^9 // = 12
Puede usarlo con booleanos y dará el resultado como 0 o 1 (que puede volver a convertir a booleanos, por ejemplo result = !!(op1 ^ op2)
). Pero como dijo John, es equivalente a result = (op1 != op2)
que es más claro.
-
Puedes usarlo como un xor lógico.
true^true
es 0, yfalse^true
es 1– Pik’
27 de diciembre de 2010 a las 17:29
-
@Pikrass Puedes usarlo como operador lógico en booleanospero no en otros tipos.
||
y&&
se pueden utilizar como operadores lógicos en no booleanos (p. ej.5 || 7
devuelve un valor verdadero,"bob" && null
devuelve un valor falso) pero^
no puedo. Por ejemplo,5 ^ 7
es igual a 2, lo cual es cierto.–Mark Amery
27/09/2014 a las 22:11
-
@Pikrass Pero lamentablemente,
(true ^ false) !== true
lo que lo hace molesto con las bibliotecas que requieren valores booleanos reales– Izkatá
1 oct 2014 a las 14:59
-
@Pikrass Nunca debe usarlo como un operador lógico en booleano porque la implementación depende del sistema operativo. estaba usando algún tipo de
a ^= true
para alternar booleanos y falla en algunas máquinas, como teléfonos.– Masadow
5 de junio de 2015 a las 15:14
-
@cronvel Claro, es solo que a veces, intentas acortar un camino súper largo como
myObj.collection[index].someImportantFlag = !myObj.collection[index].someImportantFlag
entonces era más conveniente escribirlo con^= true
. Nunca volveré a caer en la tentación 🙂– Masadow
26 de octubre de 2016 a las 9:11
El XOR de dos booleanos es simplemente si son diferentes, por lo tanto:
Boolean(a) !== Boolean(b)
-
Tuve que usar esta solución porque TypeScript se queja cuando intentas usar
^
con booleanos.– Nathan Arturo
28 de abril de 2021 a las 23:02
Roberto
No hay operadores booleanos lógicos reales en Javascript (aunque !
se acerca bastante). Un operador lógico sólo tomaría true
o false
como operandos y solo devolverían true
o false
.
En Javascript &&
y ||
tome todo tipo de operandos y devuelva todo tipo de resultados divertidos (lo que sea que los alimente).
Además, un operador lógico siempre debe tener en cuenta los valores de ambos operandos.
En Javascript &&
y ||
tomar un atajo perezoso y hacer no evaluar el segundo operando en ciertos casos y, por lo tanto, despreciar sus efectos secundarios. Este comportamiento es imposible de recrear con un xor lógico.
a() && b()
evalúa a()
y devuelve el resultado si es falso. De lo contrario, se evalúa b()
y devuelve el resultado. Por lo tanto, el resultado devuelto es verdadero si ambos resultados son verdaderos y falso en caso contrario.
a() || b()
evalúa a()
y devuelve el resultado si es veraz. De lo contrario, se evalúa b()
y devuelve el resultado. Por lo tanto, el resultado devuelto es falso si ambos resultados son falsos y verdadero en caso contrario.
Entonces, la idea general es evaluar primero el operando izquierdo. El operando correcto solo se evalúa si es necesario. Y el último valor es el resultado. Este resultado puede ser cualquier cosa. Objetos, números, cadenas… ¡lo que sea!
Esto hace posible escribir cosas como
image = image || new Image(); // default to a new Image
o
src = image && image.src; // only read out src if we have an image
Pero el valor de verdad de este resultado también se puede usar para decidir si un operador lógico “real” habría devuelto verdadero o falso.
Esto hace posible escribir cosas como
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
o
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
Pero un operador xor “lógico” (^^
) siempre tendría que evaluar ambos operandos. Esto lo hace diferente a los otros operadores “lógicos” que evalúan el segundo operando solo si es necesario. Creo que es por eso que no hay xor “lógico” en Javascript, para evitar confusiones.
Entonces, ¿qué debería pasar si ambos operandos son falsos? Ambos podrían ser devueltos. Pero solo se puede devolver uno. ¿Cuál? ¿El primero? ¿O el segundo? Mi intuición me dice que devuelva el primer pero generalmente los operadores “lógicos” evalúan de izquierda a derecha y devuelven el último valor evaluado. ¿O tal vez una matriz que contiene ambos valores?
Y si un operando es verdadero y el otro falso, un xor debe devolver el verdadero. ¿O tal vez una matriz que contenga la verdadera, para que sea compatible con el caso anterior?
Y finalmente, ¿qué debería pasar si ambos operandos son verdaderos? Esperarías algo falso. Pero no hay resultados falsos. Entonces la operación no debería devolver nada. Así que tal vez undefined
o .. una matriz vacía? Pero una matriz vacía sigue siendo verdadera.
Tomando el enfoque de matriz, terminaría con condiciones como if ((a ^^ b).length !== 1) {
. Muy confuso.
Convierta los valores en forma booleana y luego tome XOR bit a bit:
Boolean(a) ^ Boolean(b) // === 0 | 1
Tenga en cuenta que el resultado de esta expresión es un número y no un booleano.
Bitwise XOR también funciona con valores no booleanos, pero recuerde que este es un bit a bit operador, y no uno lógico. Es posible que el uso de non-bools no salga como esperaba:
(5 ^ 3) === 6 // true
4b0
Convierta a booleano y luego realice xor como –
!!a ^ !!b
el surricano
hay… una especie de:
if( foo ? !bar : bar ) {
...
}
o más fácil de leer:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
¿por qué? No sé.
porque los desarrolladores de javascript pensaron que sería innecesario ya que puede expresarse mediante otros operadores lógicos ya implementados.
también podría haber ido con nand y eso es todo, puede impresionar a todas las demás operaciones lógicas posibles a partir de eso.
Personalmente, creo que tiene razones históricas que conducen desde lenguajes de sintaxis basados en c, donde, según mi conocimiento, xor no está presente o al menos es extremadamente poco común.
-
Sí, javascript tiene operaciones ternarias.
– mwilcox
27 de diciembre de 2010 a las 18:38
-
Tanto C como Java tienen XOR usando el carácter ^ (signo de intercalación).
– veidelis
14/09/2015 a las 11:19