Jako profesjonalny matematyk widzę w operatorze podobieństwa Javscript == ( zwanym także „porównaniem abstrakcyjnym”, „luźną równość” ) próbę zbudowania relacji równoważności między jednostkami, która obejmuje bycie zwrotnym , symetrycznym i przechodnim . Niestety dwie z tych trzech podstawowych właściwości zawodzą:
A == A może być fałszywe, np
NaN == NaN // false
A == Bi B == Crazem nie oznaczają A == C, np
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Przetrwa tylko własność symetryczna :
A == Bsugeruje B == A, które naruszenie jest w każdym razie nie do pomyślenia i doprowadziłoby do poważnego buntu;)
Dlaczego stosunki równoważności mają znaczenie?
Ponieważ jest to najważniejszy i najczęstszy rodzaj relacji, poparty licznymi przykładami i aplikacjami. Najważniejszą aplikacją jest rozkład jednostek na klasy równoważności , co samo w sobie jest bardzo wygodnym i intuicyjnym sposobem rozumienia relacji. Brak równoważności prowadzi do braku klas równoważności, co z kolei prowadzi do znanego braku intuicyjności i niepotrzebnej złożoności.
Dlaczego tak okropny jest pomysł na pisanie ==relacji nierównomierności?
Ponieważ niszczy naszą znajomość i intuicję, ponieważ dosłownie każda interesująca relacja podobieństwa, równości, kongruencji, izomorfizmu, tożsamości itp. Jest równoważna.
Konwersja typu
Zamiast polegać na intuicyjnej równoważności, JavaScript wprowadza konwersję typu:
Operator równości konwertuje operandy, jeśli nie są tego samego typu, a następnie stosuje ścisłe porównanie.
Ale jak definiuje się konwersję typu? Poprzez zestaw skomplikowanych zasad z licznymi wyjątkami?
Próba zbudowania relacji równoważności
Booleany. Oczywiście truei falsenie są takie same i powinny być w różnych klasach.
Liczby. Na szczęście równość liczb jest już dobrze zdefiniowana, w której dwie różne liczby nigdy nie należą do tej samej klasy równoważności. To znaczy w matematyce. W JavaScript pojęcie liczby jest nieco zdeformowane przez obecność bardziej egzotycznych -0, Infinityi -Infinity. Nasza intuicja matematyczna dyktuje to 0i -0powinna należeć do tej samej klasy (w rzeczywistości -0 === 0jest true), podczas gdy każda z nieskończoności jest odrębną klasą.
Liczby i liczby booleańskie. Biorąc pod uwagę klasy liczbowe, gdzie umieszczamy booleany? falsestaje się podobny do 0, podczas gdy truestaje się podobny do, 1ale nie ma innej liczby:
true == 1 // true
true == 2 // false
Czy jest jakaś logika tutaj umieścić truerazem z 1? Wprawdzie 1wyróżnia się, ale tak też jest -1. Ja osobiście nie widzę żadnego powodu, aby przekształcić truesię 1.
I staje się jeszcze gorzej:
true + 2 // 3
true - 1 // 0
Tak więc truerzeczywiście jest przeliczany na 1wszystkie liczby! Czy to logiczne? Czy to jest intuicyjne? Odpowiedź pozostawia się jako ćwiczenie;)
Ale co z tym:
1 && true // true
2 && true // true
Jedyna logiczna xz x && trueistoty truejest x = true. Co dowodzi, że zarówno 1i 2(i każda inna liczba niż 0) przekształcają się true! Pokazuje to, że nasza konwersja zawodzi inna ważna właściwość - biject . Oznacza to, że dwa różne podmioty mogą konwertować na ten sam. Co samo w sobie nie musi stanowić dużego problemu. Duży problem powstaje, gdy używamy tej konwersji do opisania relacji „identyczności” lub „luźnej równości” tego, co chcemy to nazwać. Ale jedno jest jasne - nie będzie to relacja równoważności i nie będzie intuicyjnie opisana za pomocą klas równoważności.
Ale czy możemy zrobić lepiej?
Przynajmniej matematycznie - zdecydowanie tak! Prosty relacja równoważności między logicznych i numery mogą być zbudowane z tylko falsei 0będąc w tej samej klasie. Tak false == 0byłoby tylko nietrywialne luźne równość.
Co z ciągami znaków?
Możemy przycinać ciągi znaków z białych znaków na początku i na końcu, aby konwertować na liczby, a także możemy ignorować zera z przodu:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Otrzymujemy więc prostą regułę dla ciągu - przycinaj białe spacje i zera z przodu. Otrzymujemy liczbę lub pusty ciąg, w którym to przypadku konwertujemy na tę liczbę lub zero. Lub nie otrzymujemy numeru, w którym to przypadku nie dokonujemy konwersji, więc nie otrzymujemy żadnej nowej relacji.
W ten sposób moglibyśmy uzyskać idealną relację równoważności całkowitego zestawu wartości logicznych, liczb i ciągów! Tyle że ... projektanci JavaScript mają oczywiście inną opinię:
' ' == '' // false
Zatem dwa ciągi, na które oba konwertują, 0nagle stają się niepodobne! Dlaczego lub dlaczego Zgodnie z regułą struny są luźno równe dokładnie wtedy, gdy są ściśle równe! Ta reguła nie tylko łamie przechodniość, jak widzimy, ale także jest zbędna! Po co tworzyć innego operatora, ==aby był ściśle identyczny z drugim ===?
Wniosek
Luźny operator równości ==mógłby być bardzo przydatny, gdyby przestrzegał podstawowych praw matematycznych. Ale jak to niestety nie działa, jego użyteczność cierpi.