Als professioneller Mathematiker sehe ich in Javscripts Gleichheitsoperator ==
(auch als "abstrakter Vergleich", "lose Gleichheit" bezeichnet ) einen Versuch, eine Äquivalenzbeziehung zwischen Entitäten aufzubauen , die Reflexivität , Symmetrie und Transitivität einschließt . Leider schlagen zwei dieser drei grundlegenden Eigenschaften fehl:
A == A
kann falsch sein, z
NaN == NaN // false
A == B
und B == C
zusammen nicht implizieren A == C
, z
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Nur symmetrische Eigenschaften bleiben erhalten:
A == B
impliziert B == A
, welcher Verstoß wohl auf jeden Fall undenkbar ist und zu ernsthaften Aufständen führen würde;)
Warum sind Äquivalenzbeziehungen wichtig?
Denn das ist die wichtigste und häufigste Art von Beziehung, die durch zahlreiche Beispiele und Anwendungen gestützt wird. Die wichtigste Anwendung ist die Zerlegung von Entitäten in Äquivalenzklassen , was selbst eine sehr bequeme und intuitive Art ist, Beziehungen zu verstehen. Und das Versäumnis, Äquivalenz zu sein, führt zum Fehlen von Äquivalenzklassen, was wiederum zu einem Mangel an Intuitivität und unnötiger Komplexität führt, die allgemein bekannt sind.
Warum ist es so schrecklich, ==
für eine Nichtäquivalenzbeziehung zu schreiben ?
Weil es unsere Vertrautheit und Intuition bricht, ist buchstäblich jedes interessante Verhältnis von Ähnlichkeit, Gleichheit, Kongruenz, Isomorphismus, Identität usw. eine Äquivalenz.
Typkonvertierung
Anstatt sich auf eine intuitive Äquivalenz zu verlassen, führt JavaScript die Typkonvertierung ein:
Der Gleichheitsoperator konvertiert die Operanden, wenn sie nicht vom gleichen Typ sind, und wendet dann einen strengen Vergleich an.
Aber wie ist die Typkonvertierung definiert? Über eine Reihe komplizierter Regeln mit zahlreichen Ausnahmen?
Versuch, eine Äquivalenzbeziehung aufzubauen
Boolesche. Klar true
und false
sind nicht gleich und sollten in verschiedenen Klassen sein.
Zahlen. Glücklicherweise ist die Gleichheit von Zahlen bereits klar definiert, wobei zwei verschiedene Zahlen niemals in derselben Äquivalenzklasse liegen. In der Mathematik ist das so. In JavaScript ist der Begriff der Zahl etwas deformiert durch Anwesenheit des exotischere -0
, Infinity
und -Infinity
. Unsere mathematische Intuition schreibt vor, dass 0
und -0
sollte in der gleichen Klasse sein (in der Tat -0 === 0
ist true
), während jede der Unendlichkeiten eine eigene Klasse ist.
Zahlen und Boolesche Werte. Wo setzen wir angesichts der Zahlenklassen Boolesche Werte? false
wird ähnlich 0
, wohingegen true
wird ähnlich, 1
aber keine andere Zahl:
true == 1 // true
true == 2 // false
Gibt es hier eine Logik, mit der man sich true
zusammensetzen kann 1
? Zugegebenermaßen 1
wird unterschieden, aber so ist -1
. Ich persönlich sehe keinen Grund , zu konvertieren true
zu 1
.
Und es wird noch schlimmer:
true + 2 // 3
true - 1 // 0
Also true
wird in der Tat in 1
unter allen Zahlen umgerechnet ! Ist es logisch Ist es intuitiv? Die Antwort bleibt als Übung;)
Aber was ist damit:
1 && true // true
2 && true // true
Der einzige boolean x
mit x && true
Wesen true
ist x = true
. Was beweist, dass beide 1
und 2
(und jede andere Zahl als 0
) konvertieren zu true
! Was es zeigt, ist, dass unsere Konvertierung eine andere wichtige Eigenschaft versagt - die Bijektion . Dies bedeutet, dass zwei verschiedene Entitäten in dieselbe konvertiert werden können. Was für sich genommen kein großes Problem sein muss. Das große Problem entsteht, wenn wir diese Umrechnung verwenden, um ein Verhältnis von "Gleichheit" oder "loser Gleichheit" zu beschreiben, wie immer wir es nennen wollen. Aber eines ist klar - es wird keine Äquivalenzbeziehung sein und es wird nicht intuitiv über Äquivalenzklassen beschrieben.
Aber können wir es besser machen?
Zumindest mathematisch - auf jeden Fall ja! Eine einfache Äquivalenzbeziehung zwischen booleans und Zahlen kann mit nur konstruiert werden false
und 0
in der gleichen Klasse. Das false == 0
wäre also die einzige nicht triviale lose Gleichheit.
Was ist mit Streichern?
Wir können Zeichenfolgen von Leerzeichen am Anfang und am Ende abschneiden, um sie in Zahlen umzuwandeln, und wir können Nullen vor ihnen ignorieren:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Wir erhalten also eine einfache Regel für einen String - schneiden Sie die Leerzeichen und Nullen vor. Entweder erhalten wir eine Zahl oder eine leere Zeichenkette. In diesem Fall konvertieren wir in diese Zahl oder Null. Oder wir bekommen keine Zahl, in diesem Fall konvertieren wir nicht und bekommen keine neue Beziehung.
Auf diese Weise könnten wir tatsächlich eine perfekte Äquivalenzbeziehung für die Gesamtmenge der Booleschen Werte, Zahlen und Zeichenfolgen erhalten! Ausgenommen, dass ... JavaScript-Designer offensichtlich eine andere Meinung haben:
' ' == '' // false
Die beiden Zeichenfolgen, in die beide konvertieren, 0
sind also plötzlich nicht mehr ähnlich! Warum oder warum? Nach der Regel sind Strings genau dann lose gleich, wenn sie genau gleich sind! Diese Regel bricht nicht nur die Transitivität, wie wir sehen, sondern ist auch überflüssig! Was bringt es, einen anderen Operator ==
zu erstellen , um ihn genau mit dem anderen Operator zu identisch zu machen ===
?
Fazit
Der lose Gleichheitsoperator ==
hätte sehr nützlich sein können, wenn er sich an einige grundlegende mathematische Gesetze gehalten hätte. Aber wie es leider nicht tut, leidet seine Nützlichkeit.