Warum gibt es kein logisches XOR?

Lesezeit: 6 Minuten

Benutzeravatar von DarkLightA
DarkLightA

Warum gibt es keine logische XOR in JavaScript?

John Kugelmans Benutzeravatar
John Kugelmann

JavaScript geht auf C zurück, und C verfügt über keinen logischen XOR-Operator. Vor allem, weil es nicht nützlich ist. Bitweises XOR ist äußerst nützlich, aber in all meinen Programmierjahren habe ich nie ein logisches XOR benötigt.

Wenn Sie zwei boolesche Variablen haben, können Sie XOR nachahmen mit:

if (a != b)

Mit zwei beliebigen Variablen könnten Sie verwenden ! um sie auf boolesche Werte zu zwingen und dann den gleichen Trick anzuwenden:

if (!a != !b)

Das ist allerdings ziemlich unklar und würde sicherlich einen Kommentar verdienen. Tatsächlich könnten Sie an dieser Stelle sogar den bitweisen XOR-Operator verwenden, obwohl dies für meinen Geschmack viel zu clever wäre:

if (!a ^ !b)

  • Das einzige Problem mit != ist, dass man nicht das Gleiche tun kann a ^= bWeil a !== b ist einfach das strenge Ungleichheit Operator.

    – mcpiroman

    2. Januar 2020 um 19:34

  • Solange Sie bereits zwei boolesche Variablen haben, a Und b, XOR ist tatsächlich überflüssig. Aber Menschen brauchen im Allgemeinen keine booleschen Operationen, wenn sie bereits boolesche Variablen haben. Du tust es nie const a = foo == bar; if (a == true) { console.log("foo=bar"); } Der eigentliche Sinn boolescher Operationen besteht darin, einfache Inline-Tests zu ermöglichen, die vom Compiler optimiert werden, ohne den Aufwand für die Definition überflüssiger Variablen.

    – Bogdan Stăncescu

    26. Dezember 2020 um 19:30 Uhr


Piks Benutzeravatar
Pik’

Javascript hat einen bitweisen XOR-Operator: ^

var nb = 5^9 // = 12

Sie können es mit Booleschen Werten verwenden und das Ergebnis wird als 0 oder 1 ausgegeben (den Sie wieder in einen Booleschen Wert umwandeln können, z. B result = !!(op1 ^ op2)). Aber wie John sagte, es ist gleichbedeutend mit result = (op1 != op2)was klarer ist.

  • Sie können es als logisches XOR verwenden. true^true ist 0, und false^true ist 1.

    – Pik’

    27. Dezember 2010 um 17:29

  • @Pikrass Sie können es als logischen Operator verwenden auf Booleschen Wertenaber nicht bei anderen Typen. || Und && können als logische Operatoren für nicht-boolesche Werte verwendet werden (z. B 5 || 7 gibt einen wahren Wert zurück, "bob" && null gibt einen falschen Wert zurück), aber ^ kann nicht. Zum Beispiel, 5 ^ 7 gleich 2, was der Wahrheit entspricht.

    – Mark Amery

    27. September 2014 um 22:11 Uhr


  • @Pikrass Aber leider, (true ^ false) !== truewas bei Bibliotheken, die tatsächliche Boolesche Werte erfordern, ärgerlich ist

    – Izkata

    1. Okt. 2014 um 14:59

  • @Pikrass Sie sollten es niemals als logischen Operator für boolesche Werte verwenden, da die Implementierung vom Betriebssystem abhängt. Ich habe irgendeine Art von verwendet a ^= true um boolesche Werte umzuschalten, was auf einigen Computern wie Telefonen fehlschlägt.

    – Masadow

    5. Juni 2015 um 15:14


  • @cronvel Klar, es ist nur so, dass man manchmal versucht, superlange Pfade zu verkürzen, z myObj.collection[index].someImportantFlag = !myObj.collection[index].someImportantFlag Daher war es bequemer, damit zu schreiben ^= true. Ich werde nie wieder in Versuchung geraten 🙂

    – Masadow

    26. Oktober 2016 um 9:11 Uhr

Das XOR zweier boolescher Werte ist einfach, ob sie unterschiedlich sind, daher:

Boolean(a) !== Boolean(b)

  • Ich musste diese Lösung verwenden, da sich TypeScript beschwert, wenn Sie versuchen, es zu verwenden ^ mit Booleschen Werten.

    – Nathan Arthur

    28. April 2021 um 23:02 Uhr

Roberts Benutzeravatar
Robert

Es gibt in Javascript keine echten logischen booleschen Operatoren (obwohl ! kommt schon ziemlich nahe). Ein logischer Operator würde nur dauern true oder false als Operanden und würde nur zurückkehren true oder false.

In Javascript && Und || Nehmen Sie alle Arten von Operanden und geben Sie alle möglichen lustigen Ergebnisse zurück (was auch immer Sie in sie eingeben).

Auch ein logischer Operator sollte immer die Werte beider Operanden berücksichtigen.

In Javascript && Und || Nehmen Sie eine faule Abkürzung und tun Sie es nicht In bestimmten Fällen den zweiten Operanden auswerten und dadurch seine Nebenwirkungen vernachlässigen. Dieses Verhalten kann mit einem logischen XOR nicht wiederhergestellt werden.


a() && b() wertet aus a() und gibt das Ergebnis zurück, wenn es falsch ist. Ansonsten wird ausgewertet b() und gibt das Ergebnis zurück. Daher ist das zurückgegebene Ergebnis wahr, wenn beide Ergebnisse wahr sind, andernfalls falsch.

a() || b() wertet aus a() und gibt das Ergebnis zurück, wenn es wahr ist. Ansonsten wird ausgewertet b() und gibt das Ergebnis zurück. Daher ist das zurückgegebene Ergebnis falsch, wenn beide Ergebnisse falsch sind, andernfalls wahr.

Die allgemeine Idee besteht also darin, zuerst den linken Operanden auszuwerten. Der rechte Operand wird nur bei Bedarf ausgewertet. Und der letzte Wert ist das Ergebnis. Dieses Ergebnis kann alles sein. Objekte, Zahlen, Strings … was auch immer!

Dadurch ist es möglich, Dinge zu schreiben wie

image = image || new Image(); // default to a new Image

oder

src = image && image.src; // only read out src if we have an image

Der Wahrheitswert dieses Ergebnisses kann aber auch verwendet werden, um zu entscheiden, ob ein „echter“ logischer Operator wahr oder falsch zurückgegeben hätte.

Dadurch ist es möglich, Dinge zu schreiben wie

if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {

oder

if (image.hasAttribute('alt') || image.hasAttribute('title')) {

Aber ein „logischer“ xor-Operator (^^) müsste immer beide Operanden auswerten. Dies unterscheidet ihn von den anderen „logischen“ Operatoren, die den zweiten Operanden nur bei Bedarf auswerten. Ich denke, das ist der Grund, warum es in Javascript kein „logisches“ xor gibt, um Verwirrung zu vermeiden.


Was soll also passieren, wenn beide Operanden falsch sind? Beide konnten zurückgegeben werden. Es kann aber nur einer zurückgegeben werden. Welcher? Der erste? Oder der zweite? Meine Intuition sagt mir, dass ich die ersten, aber normalerweise „logischen“ Operatoren von links nach rechts auswerten und den zuletzt ausgewerteten Wert zurückgeben soll. Oder vielleicht ein Array, das beide Werte enthält?

Und wenn ein Operand wahr und der andere falsch ist, sollte ein XOR den wahren Operanden zurückgeben. Oder vielleicht ein Array, das das Wahre enthält, um es mit dem vorherigen Fall kompatibel zu machen?

Und schließlich: Was sollte passieren, wenn beide Operanden wahr sind? Man würde etwas Falsches erwarten. Aber es gibt keine falschen Ergebnisse. Der Vorgang sollte also nichts zurückgeben. Also vielleicht undefined oder .. ein leeres Array? Aber ein leeres Array ist immer noch wahr.

Wenn Sie den Array-Ansatz verwenden, erhalten Sie Bedingungen wie if ((a ^^ b).length !== 1) {. Sehr verwirrend.

Werte in boolesche Form umwandeln und dann übernehmen bitweises XOR:

Boolean(a) ^ Boolean(b) // === 0 | 1

Beachten Sie, dass das Ergebnis dieses Ausdrucks a ist Nummer Und nicht ein Boolescher Wert.

Bitweises XOR funktioniert auch mit nicht-booleschen Werten, aber denken Sie daran, dass dies ein ist bitweise Operator und kein logischer. Die Verwendung von Nicht-Bools verläuft möglicherweise nicht wie erwartet:

(5 ^ 3) === 6 // true

Benutzeravatar von 4b0
4b0

In einen Booleschen Wert umwandeln und dann xor wie ausführen –

!!a ^ !!b

Der Benutzeravatar des Surrican
Der Surricaner

es gibt… sozusagen:

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

oder einfacher zu lesen:

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

Warum? Keine Ahnung.

weil Javascript-Entwickler dachten, es wäre unnötig, da es durch andere, bereits implementierte logische Operatoren ausgedrückt werden kann.

Sie könnten genauso gut einfach nand verwenden und das war’s, Sie können daraus jede andere mögliche logische Operation abbilden.

Ich persönlich denke, dass es historische Gründe hat, die von C-basierten Syntaxsprachen ausgehen, in denen xor meines Wissens nicht vorhanden oder zumindest äußerst ungewöhnlich ist.

  • Ja, Javascript verfügt über ternäre Operationen.

    – mwilcox

    27. Dezember 2010 um 18:38

  • Sowohl C als auch Java verfügen über XOR mit dem Zeichen ^ (Caret).

    – veidelis

    14. September 2015 um 11:19 Uhr

1454630cookie-checkWarum gibt es kein logisches XOR?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy