Por que não há xor lógico em JavaScript?
javascript
xor
logical-operators
DarkLightA
fonte
fonte
!=
é que você não pode fazer o mesmo quea ^= b
, porquea !== b
é apenas o operador de desigualdade estrita .Javascript tem um operador XOR bit a bit: ^
Você pode usá-lo com booleanos e ele fornecerá o resultado como 0 ou 1 (que você pode converter novamente em booleano, por exemplo
result = !!(op1 ^ op2)
). Mas, como John disse, é equivalenteresult = (op1 != op2)
, o que é mais claro.fonte
true^true
é 0 efalse^true
é 1.||
e&&
pode ser usado como operadores lógicos em não-booleanos (por exemplo5 || 7
,"bob" && null
retorna um valor verdadeiro , retorna um valor falsey), mas^
não pode. Por exemplo,5 ^ 7
é igual a 2, que é verdade.(true ^ false) !== true
que o torna irritante com bibliotecas que exigem booleans reaisa ^= true
alternância de booleanos e ele falha em algumas máquinas, como telefones.Não há operadores booleanos lógicos reais em Javascript (embora
!
cheguem bem perto). Um operador lógico usaria apenastrue
oufalse
como operandos e retornariatrue
oufalse
.Em Javascript
&&
e||
tomar todos os tipos de operandos e devolver todos os tipos de resultados engraçados (o que você alimentam-los).Além disso, um operador lógico sempre deve levar em consideração os valores de ambos os operandos.
Em Javascript
&&
e||
tomar um atalho preguiçoso e que não avalia o segundo operando em certos casos e, assim, negligenciar seus efeitos colaterais. É impossível recriar esse comportamento com um xor lógico.a() && b()
avaliaa()
e retorna o resultado se for falso. Caso contrário, ele avaliab()
e retorna o resultado. Portanto, o resultado retornado é verdadeiro se ambos forem verdadeiros e, caso contrário, falso.a() || b()
avaliaa()
e retorna o resultado, se for verdade. Caso contrário, ele avaliab()
e retorna o resultado. Portanto, o resultado retornado é falso se ambos os resultados forem falsos e, de outra forma, verdadeiro.Portanto, a ideia geral é avaliar primeiro o operando esquerdo. O operando certo é avaliado apenas se necessário. E o último valor é o resultado. Este resultado pode ser qualquer coisa. Objetos, números, strings .. tanto faz!
Isso possibilita escrever coisas como
ou
Mas o valor verdadeiro desse resultado também pode ser usado para decidir se um operador lógico "real" retornaria verdadeiro ou falso.
Isso possibilita escrever coisas como
ou
Mas um operador xor "lógico" (
^^
) sempre precisaria avaliar os dois operandos. Isso o torna diferente dos outros operadores "lógicos" que avaliam o segundo operando somente se necessário. Eu acho que é por isso que não há xor "lógico" em Javascript, para evitar confusão.Então, o que deve acontecer se ambos os operandos forem falsos? Ambos podem ser devolvidos. Mas apenas um pode ser devolvido. Qual? O primeiro? Ou o segundo? Minha intuição me diz para retornar os primeiros operadores, mas geralmente "lógicos", da esquerda para a direita e retornar o último valor avaliado. Ou talvez uma matriz contendo os dois valores?
E se um operando é verdadeiro e o outro operando é falso, um xor deve retornar o verdadeiro. Ou talvez uma matriz contendo a verdade, para torná-la compatível com o caso anterior?
E, finalmente, o que deve acontecer se os dois operandos forem verdadeiros? Você esperaria algo falso. Mas não há resultados falsos. Portanto, a operação não deve retornar nada. Então talvez
undefined
ou .. uma matriz vazia? Mas uma matriz vazia ainda é verdadeira.Tomando a abordagem de matriz, você acabaria com condições como
if ((a ^^ b).length !== 1) {
. Muito confuso.fonte
O XOR de dois booleanos é simplesmente se eles são diferentes, portanto:
fonte
Converta valores no formato booleano e, em seguida, use o XOR bit a bit. Também ajudará com valores não-booleanos.
fonte
Encoberto para booleano e, em seguida, execute xor como -
fonte
!!a ^ !!b
é equivalente a!a ^ !b
. Argumentos poderiam ser feitos sobre qual é mais fácil de ler.existe ... mais ou menos:
ou mais fácil de ler:
porque? Não sei.
porque os desenvolvedores de javascript pensaram que seria desnecessário, pois pode ser expresso por outros operadores lógicos já implementados.
você também pode simplesmente usar o nand e é isso, pode impressionar qualquer outra operação lógica possível a partir disso.
Pessoalmente, acho que há razões históricas que partem de linguagens de sintaxe baseadas em c, onde, até onde sei, xor não está presente ou, pelo menos, extremamente incomum.
fonte
Sim, faça o seguinte. Supondo que você esteja lidando com os booleanos A e B, o valor A XOR B pode ser calculado em JavaScript usando o seguinte
A linha anterior também é equivalente à seguinte
Pessoalmente, prefiro xor1, pois tenho que digitar menos caracteres. Eu acredito que o xor1 também é mais rápido também. É apenas realizar dois cálculos. O xor2 está realizando três cálculos.
Explicação visual ... Leia a tabela abaixo (onde 0 significa falso e 1 significa verdadeiro) e compare as 3ª e 5ª colunas.
! (A === B):
Aproveitar.
fonte
var xor1 = !(a === b);
é o mesmo quevar xor1 = a !== b;
!(2 === 3)
étrue
, mas2
e3
é verdade ,2 XOR 3
deveria serfalse
.Verificação de saída:
Você pode imitar algo assim:
fonte
Que tal transformar o resultado int em um bool com dupla negação? Não é tão bonito, mas muito compacto.
fonte
B = ((!state1)!==(!state2))
B =!!(!state1 ^ !state2);
Além disso, por que tantos parênteses?B = !state1 !== !state2;
Ou você pode até ignorar a negação:B = state1 !== state2;
state1 !== state2
, não é necessário fazer nenhuma conversão lá, pois!==
é um operador lógico, não um pouco.12 !== 4
é verdade'xy' !== true
também é verdade. Se você usasse em!=
vez de!==
, teria que fazer a transmissão.!==
e!=
é sempre booleano ... não sei qual deveria ser a distinção que você está fazendo, esse não é absolutamente o problema. O problema é que o operador XOR que queremos é realmente a expressão(Boolean(state1) !== Boolean(state2))
. Para booleanos, "xy", 12, 4 etrue
são todos os valores verdadeiros e devem ser convertidos emtrue
. assim("xy" XOR true)
deve serfalse
, mas("xy" !== true)
étrue
, como você aponta. Portanto,!==
ou!=
são (ambos) equivalentes a "XOR lógico" se e somente se você converter seus argumentos em booleanos antes de aplicar.Na função xor acima, ele resultará em resultado SIMILAR, pois xor lógico não é exatamente xor lógico, significa que resultará "falso para valores iguais" e "verdadeiro para valores diferentes", com a consideração do tipo de dados em consideração.
Esta função XOR funcionará como xor real ou operador lógico , meios que irão resultar verdadeira ou falsa acordo com os valores que passam são truthy ou Falsas . Use de acordo com suas necessidades
fonte
(!!x) === (!!y)
. A diferença é uma conversão para booleano.'' === 0
é falso, enquantoxnor('', 0)
é verdadeiro.Em Texto datilografado (o + muda para o valor numérico):
Assim:
fonte
!!(false ^ true)
funciona bem com booleanos. No texto datilografado, + é necessário para torná-lo válido!!(+false ^ +true)
.cond1 xor cond2
é equivalente acond1 + cond 2 == 1
:Aqui está a prova:
fonte
A razão pela qual não existe um XOR lógico (^^) é porque diferente de && e || não oferece nenhuma vantagem de lógica preguiçosa. Esse é o estado de ambas as expressões à direita e à esquerda devem ser avaliadas.
fonte
Aqui está uma solução alternativa que funciona com mais de 2 variáveis e fornece contagem como bônus.
Aqui está uma solução mais geral para simular XOR lógico para quaisquer valores de verdade / falsey, como se você tivesse o operador nas instruções IF padrão:
A razão de eu gostar disso é porque ela também responde "Quantas dessas variáveis são verdadeiras?", Então eu costumo pré-armazenar esse resultado.
E para aqueles que desejam um comportamento estrito de verificação booleana-TRUE xor, basta fazer:
Se você não se importa com a contagem ou com o desempenho ideal: basta usar o xor bit a bit em valores coagidos a booleanos, para a solução de verdade / falsidade:
fonte
Ei, eu encontrei esta solução, para fazer e XOR em JavaScript e TypeScript.
fonte
Experimente este breve e fácil de entender
Isso funcionará para qualquer tipo de dados
fonte
true == someboolean
não é necessário fazer, então, na verdade, o que você fez é agrupar os estritos não iguais em uma função.