Dlaczego w JavaScript nie ma logicznego xor?
javascript
xor
logical-operators
DarkLightA
źródło
źródło
!=
polega na tym, że nie można zrobić tego samegoa ^= b
, ponieważa !== b
jest to tylko operator ścisłej nierówności .JavaScript ma bitowy operator XOR: ^
Możesz go używać z wartościami logicznymi, a wynik da 0 lub 1 (które możesz przekonwertować z powrotem na wartość logiczną, np
result = !!(op1 ^ op2)
.). Ale jak powiedział John, jest to równoważneresult = (op1 != op2)
, co jest wyraźniejsze.źródło
true^true
wynosi 0, afalse^true
wynosi 1.||
i&&
mogą być używane jako operatory logiczne na5 || 7
obiektach niebędących wartościami logicznymi (np. zwracają prawdziwą wartość,"bob" && null
zwracają wartość falsey), ale^
nie mogą. Na przykład5 ^ 7
równa się 2, co jest zgodne z prawdą.(true ^ false) !== true
co sprawia, że jest denerwujące w bibliotekach, które wymagają rzeczywistycha ^= true
przełączania booleanów, a to nie działa na niektórych komputerach, takich jak telefony.W Javascript nie ma prawdziwych logicznych operatorów boolowskich (choć
!
jest całkiem blisko). Operator logiczny wziąłby tylkotrue
lubfalse
jako operandy i zwróciłby tylkotrue
lubfalse
.W Javascript
&&
i||
bierz wszystkie operandy i zwracaj różnego rodzaju zabawne wyniki (cokolwiek do nich dodajesz).Również operator logiczny powinien zawsze brać pod uwagę wartości obu operandów.
W JavaScript
&&
i||
weź leniwy skrót i nie oceniaj drugiego operandu w niektórych przypadkach, a tym samym zaniedbujesz jego skutki uboczne. To zachowanie jest niemożliwe do odtworzenia przy użyciu logicznego xor.a() && b()
oceniaa()
i zwraca wynik, jeśli jest to fałsz. W przeciwnym razie oceniab()
i zwraca wynik. Dlatego zwrócony wynik jest prawdziwy, jeśli oba wyniki są prawdziwe, a fałsz jest inny.a() || b()
oceniaa()
i zwraca wynik, jeśli jest zgodny z prawdą. W przeciwnym razie oceniab()
i zwraca wynik. Dlatego zwrócony wynik jest fałszem, jeśli oba wyniki są fałszem, a tak naprawdę jest inaczej.Zatem ogólną ideą jest najpierw ocena lewego operandu. Właściwy operand jest oceniany tylko w razie potrzeby. I ostatnia wartość jest wynikiem. Ten wynik może być dowolny. Obiekty, liczby, ciągi znaków ... cokolwiek!
Umożliwia to pisanie takich rzeczy
lub
Ale wartość prawdy tego wyniku można również wykorzystać do podjęcia decyzji, czy „prawdziwy” operator logiczny zwróciłby wartość prawda czy fałsz.
Umożliwia to pisanie takich rzeczy
lub
Ale „logiczny” operator xor (
^^
) zawsze musiałby oceniać oba operandy. To odróżnia go od innych operatorów „logicznych”, które oceniają drugi argument tylko w razie potrzeby. Myślę, że właśnie dlatego w Javascript nie ma „logicznej” xor, aby uniknąć nieporozumień.Co więc powinno się stać, jeśli oba operandy są fałszywe? Oba można zwrócić. Ale tylko jeden może zostać zwrócony. Który? Pierwszy? A może drugi? Moja intuicja każe mi zwrócić pierwsze, ale zwykle „logiczne” operatory oceniają od lewej do prawej i zwracają ostatnią ocenianą wartość. A może tablica zawierająca obie wartości?
A jeśli jeden operand jest prawdziwy, a drugi operant jest fałszem, xor powinien zwrócić prawdomówny. A może tablica zawierająca prawdziwą, aby była kompatybilna z poprzednim przypadkiem?
I wreszcie, co powinno się stać, jeśli oba operandy są prawdziwe? Spodziewałbyś się czegoś fałszywego. Ale nie ma wyników fałszywych. Więc operacja nie powinna niczego zwracać. Więc może
undefined
lub ... pusta tablica? Ale pusta tablica jest nadal prawdą.Przyjmując podejście tablicowe, skończyłbyś z takimi warunkami
if ((a ^^ b).length !== 1) {
. Bardzo mylące.źródło
XOR dwóch booleanów polega na tym, czy są one różne, dlatego:
źródło
Konwertuj wartości na postać logiczną, a następnie weź bitową XOR. Pomoże to również w przypadku wartości innych niż boolowskie.
źródło
Ukryj do wartości logicznej, a następnie wykonaj xor jak -
źródło
!!a ^ !!b
jest to równoważne z!a ^ !b
. Można argumentować, co jest łatwiejsze do odczytania.jest ... rodzaj:
lub łatwiejsze do odczytania:
czemu? Dunno.
ponieważ programiści javascript uważali, że byłoby to niepotrzebne, ponieważ mogą wyrazić to inne, już zaimplementowane, operatory logiczne.
równie dobrze możesz po prostu skończyć z nand i to wszystko, możesz wywrzeć na nim wrażenie z każdej innej logicznej operacji.
osobiście uważam, że ma to historyczne powody, które napędzają języki składniowe oparte na c, gdzie według mojej wiedzy xor nie jest obecny lub przynajmniej wyjątkowo rzadki.
źródło
Tak, po prostu wykonaj następujące czynności. Zakładając, że masz do czynienia z booleanami A i B, wówczas wartość A XOR B można obliczyć w JavaScript za pomocą następującego
Poprzedni wiersz jest również równoważny z poniższym
Osobiście wolę xor1, ponieważ muszę pisać mniej znaków. Wierzę, że xor1 też jest szybszy. Po prostu wykonuje dwa obliczenia. xor2 wykonuje trzy obliczenia.
Objaśnienie wizualne ... Przeczytaj poniższą tabelę (gdzie 0 oznacza fałsz, a 1 oznacza prawda) i porównaj 3 i 5 kolumnę.
! (A === B):
Cieszyć się.
źródło
var xor1 = !(a === b);
jest taki sam jakvar xor1 = a !== b;
!(2 === 3)
jesttrue
, ale2
i3
są prawdą, tak2 XOR 3
powinno byćfalse
.Sprawdzić:
Możesz naśladować coś takiego:
źródło
Co powiesz na przekształcenie wyniku int w bool z podwójną negacją? Nie tak ładny, ale naprawdę kompaktowy.
źródło
B = ((!state1)!==(!state2))
B =!!(!state1 ^ !state2);
Dlaczego więc tak wiele nawiasów?B = !state1 !== !state2;
Lub możesz nawet porzucić negację:B = state1 !== state2;
state1 !== state2
, nie musisz tam wykonywać rzutowania, ponieważ!==
jest operatorem logicznym, nie trochę.12 !== 4
prawda'xy' !== true
jest również prawdą. Jeśli użyjesz!=
zamiast tego!==
, będziesz musiał wykonać casting.!==
i!=
jest zawsze logiczna ... nie wiem, co rozróżnienie robisz tam ma być, to nie jest absolutnie problem. Problem polega na tym, że operator XOR, którego chcemy, jest naprawdę wyrażeniem(Boolean(state1) !== Boolean(state2))
. W przypadku wartości logicznych „xy”, 12, 4 itrue
wszystkie są prawdziwymi wartościami i powinny zostać przekonwertowane natrue
. tak("xy" XOR true)
powinno byćfalse
, ale("xy" !== true)
jesttrue
, jak wskazałeś. Tak więc!==
lub!=
są (oba) równoważne z „logicznym XOR” tylko wtedy i tylko wtedy , gdy przekonwertujesz ich argumenty na logiczne przed zastosowaniem.W powyższej funkcji xor spowoduje PODOBNY wynik, ponieważ xor logiczny nie do końca logiczny xor, oznacza „false dla równych wartości” i „true dla różnych wartości” z typu danych dopasowywania pod uwagę.
Ta funkcja xor będzie działać jako rzeczywisty xor lub operator logiczny , co oznacza, że spowoduje uzyskanie wartości true lub false zgodnie z przekazywanymi wartościami true lub fałsz . Używaj zgodnie z własnymi potrzebami
źródło
(!!x) === (!!y)
. Różnica polega na obsadzie na boolean.'' === 0
jest fałszywe, axnor('', 0)
prawda.W maszynopisie (+ zmienia się na wartość liczbową):
Więc:
źródło
!!(false ^ true)
działa dobrze z logami. W maszynopisie wymagane jest +, aby było prawidłowe!!(+false ^ +true)
.cond1 xor cond2
jest równacond1 + cond 2 == 1
:Oto dowód:
źródło
Przyczyną braku logicznego XOR (^^) jest to, że w przeciwieństwie do && i || nie daje żadnej przewagi logicznej. Taki jest stan obu wyrażeń po prawej i lewej stronie.
źródło
Oto alternatywne rozwiązanie, które działa z 2+ zmiennymi i zapewnia liczenie jako bonus.
Oto bardziej ogólne rozwiązanie do symulacji logicznego XOR dla dowolnych wartości true / falsey, tak jakbyś miał operatora w standardowych instrukcjach IF:
Powodem, dla którego mi się to podoba, jest to, że odpowiada również „Ile z tych zmiennych jest prawdziwych?”, Więc zwykle przechowuję ten wynik wcześniej.
A dla tych, którzy chcą ścisłego zachowania logicznego PRAWDA xor, sprawdź:
Jeśli nie zależy ci na liczeniu lub zależy Ci na optymalnej wydajności: po prostu użyj bitowej xor na wartościach wymuszonych na wartość logiczną, aby uzyskać rozwiązanie typu prawda / fałsz:
źródło
Hej Znalazłem to rozwiązanie, do zrobienia i XOR w JavaScript i TypeScript.
źródło
Wypróbuj to krótkie i łatwe do zrozumienia
Będzie to działać dla dowolnego typu danych
źródło
true == someboolean
nie jest konieczne, więc tak naprawdę to, co zrobiłeś, jest zawinięcie ścisłej funkcji nie-równości w funkcję.