Wiele operatorów porównania znamy z matematyki.
W JavaScript pisze się je tak:
- Greater/less than:
a > b
,a < b
. - Większe/mniejsze niż lub równe:
a >= b
,a <= b
. - Equals:
a == b
, proszę zwrócić uwagę na podwójny znak równości==
oznacza test równości, natomiast pojedynczya = b
oznacza przyporządkowanie. - Nie równe. W matematyce jest to
≠
, ale w JavaScript zapisuje się to jakoa != b
.
W tym artykule dowiemy się więcej o różnych typach porównań, jak JavaScript je wykonuje, w tym o ważnych osobliwościach.
Na końcu znajdziesz dobrą receptę na uniknięcie problemów związanych z „dziwactwami JavaScript”.
Boolean is the result
Wszystkie operatory porównania zwracają wartość boolean:
-
true
– oznacza „tak”, „poprawny” lub „prawdę”. -
false
– oznacza „nie”, „błędny” lub „nie prawdę”.
Na przykład:
alert( 2 > 1 ); // true (correct)alert( 2 == 1 ); // false (wrong)alert( 2 != 1 ); // true (correct)
Wynik porównania można przypisać do zmiennej, tak jak każdą wartość:
let result = 5 > 4; // assign the result of the comparisonalert( result ); // true
Porównanie ciągów znaków
Aby sprawdzić, czy dany ciąg znaków jest większy od innego, JavaScript używa tzw. porządku „słownikowego” lub „leksykograficznego”.
Innymi słowy, ciągi są porównywane litera po literze.
Na przykład:
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
Algorytm porównywania dwóch ciągów jest prosty:
- Porównaj pierwszy znak obu ciągów.
- Jeśli pierwszy znak z pierwszego ciągu jest większy (lub mniejszy) od znaku drugiego ciągu, to pierwszy ciąg jest większy (lub mniejszy) od drugiego. Skończyliśmy.
- W przeciwnym razie, jeśli pierwsze znaki obu ciągów są takie same, porównaj drugie znaki w ten sam sposób.
- Powtarzaj aż do końca jednego z ciągów.
- Jeśli oba ciągi kończą się na tej samej długości, to są równe. W przeciwnym razie, dłuższy ciąg jest większy.
W pierwszym przykładzie powyżej, porównanie 'Z' > 'A'
dostaje się do wyniku w pierwszym kroku.
Drugie porównanie 'Glow'
i 'Glee'
wymaga więcej kroków, ponieważ ciągi są porównywane znak po znaku:
-
G
jest taki sam jakG
. -
l
jest taki sam jakl
. -
o
jest większy niże
. Zatrzymaj się tutaj. Pierwszy ciąg jest większy.
Algorytm porównywania podany powyżej jest z grubsza równoważny temu używanemu w słownikach lub książkach telefonicznych, ale nie jest dokładnie taki sam.
Na przykład wielkość liter ma znaczenie. Duża litera "A"
nie jest równa małej "a"
. Która z nich jest większa? Mała litera "a"
. Dlaczego? Ponieważ mały znak ma większy indeks w wewnętrznej tabeli kodowania, której używa JavaScript (Unicode). Do konkretnych szczegółów i konsekwencji tego wrócimy w rozdziale Strings.
Porównywanie różnych typów
Przy porównywaniu wartości różnych typów JavaScript konwertuje wartości na liczby.
Na przykład:
alert( '2' > 1 ); // true, string '2' becomes a number 2alert( '01' == 1 ); // true, string '01' becomes a number 1
Dla wartości boolean, true
staje się 1
, a false
staje się 0
.
Na przykład:
alert( true == 1 ); // truealert( false == 0 ); // true
Możliwe jest, że w tym samym czasie:
- Dwie wartości są równe.
- Jedna z nich to
true
jako boolean, a druga tofalse
jako boolean.
Na przykład:
let a = 0;alert( Boolean(a) ); // falselet b = "0";alert( Boolean(b) ); // truealert(a == b); // true!
Z punktu widzenia JavaScriptu ten wynik jest całkiem normalny. Kontrola równości konwertuje wartości używając konwersji numerycznej (stąd "0"
staje się 0
), podczas gdy jawna konwersja Boolean
używa innego zestawu reguł.
Ścisła równość
Zwykła kontrola równości ==
ma problem. Nie potrafi odróżnić 0
od false
:
alert( 0 == false ); // true
To samo dzieje się z pustym ciągiem:
alert( '' == false ); // true
Dzieje się tak, ponieważ operandy różnych typów są konwertowane na liczby przez operator równości ==
. Pusty łańcuch, podobnie jak false
, staje się zerem.
Co zrobić, jeśli chcielibyśmy odróżnić 0
od false
?
Ścisły operator równości ===
sprawdza równość bez konwersji typów.
Innymi słowy, jeśli a
i b
są różnych typów, to a === b
natychmiast zwraca false
bez próby ich konwersji.
Spróbujmy to:
alert( 0 === false ); // false, because the types are different
Istnieje również operator „ścisłej nierówności” !==
analogiczny do !=
.
Ścisły operator równości jest nieco dłuższy do napisania, ale sprawia, że jest oczywiste, co się dzieje i pozostawia mniej miejsca na błędy.
Porównanie z null i undefined
Istnieje nieintuicyjne zachowanie, gdy null
lub undefined
są porównywane z innymi wartościami.
Dla ścisłego sprawdzenia równości===
Te wartości są różne, ponieważ każda z nich jest innego typu.
alert( null === undefined ); // false
Dla nie ścisłego sprawdzenia==
Istnieje specjalna reguła. Te dwie wartości są „słodką parą”: są sobie równe (w sensie ==
), ale nie żadnej innej wartości.
alert( null == undefined ); // true
Dla matematyki i innych porównań< > <= >=
null/undefined
są zamieniane na liczby: null
staje się 0
, natomiast undefined
staje się NaN
.
Zobaczmy teraz kilka zabawnych rzeczy, które dzieją się, gdy zastosujemy te zasady. I, co ważniejsze, jak nie wpaść z nimi w pułapkę.
Dziwny wynik: null vs 0
Porównajmy null
z zerem:
alert( null > 0 ); // (1) falsealert( null == 0 ); // (2) falsealert( null >= 0 ); // (3) true
Matematycznie rzecz biorąc, jest to dziwne. Ostatni wynik stwierdza, że „null
jest większe lub równe zero”, więc w jednym z powyższych porównań musi to być true
, ale oba są fałszywe.
Powodem jest to, że sprawdzanie równości ==
i porównania > < >= <=
działają inaczej. Porównania konwertują null
na liczbę, traktując ją jako 0
. Dlatego (3) null >= 0
jest prawdziwe, a (1) null > 0
jest fałszywe.
Z drugiej strony, sprawdzanie równości ==
dla undefined
i null
jest zdefiniowane tak, że bez żadnych konwersji są one sobie równe i nie równają się niczemu innemu. Dlatego (2) null == 0
jest fałszywe.
An incomparable undefined
Wartość undefined
nie powinna być porównywana z innymi wartościami:
alert( undefined > 0 ); // false (1)alert( undefined < 0 ); // false (2)alert( undefined == 0 ); // false (3)
Dlaczego tak bardzo nie lubi zera? Zawsze false!
Otrzymujemy te wyniki, ponieważ:
- Porównania
(1)
i(2)
zwracająfalse
, ponieważundefined
zostaje przekonwertowane naNaN
, aNaN
jest specjalną wartością liczbową, która zwracafalse
dla wszystkich porównań. - Sprawdzanie równości
(3)
zwracafalse
, ponieważundefined
jest równe tylkonull
,undefined
i żadnej innej wartości.
Unikaj problemów
Dlaczego przeszliśmy przez te przykłady? Czy powinniśmy cały czas pamiętać o tych osobliwościach? Cóż, nie bardzo. Właściwie te podstępne rzeczy z czasem stopniowo staną się znane, ale istnieje solidny sposób na uniknięcie problemów z nimi:
- Traktuj każde porównanie z
undefined/null
z wyjątkiem ścisłej równości===
z wyjątkową ostrożnością. - Nie używaj porównań
>= > < <=
ze zmienną, która może byćnull/undefined
, chyba że jesteś naprawdę pewien tego, co robisz. Jeśli zmienna może mieć takie wartości, sprawdź je osobno.
Podsumowanie
- Operatory porównania zwracają wartość boolean.
- Stringi są porównywane litera po literze w kolejności „słownikowej”.
- Gdy porównywane są wartości różnych typów, zostają one przekonwertowane na liczby (z wyłączeniem ścisłego sprawdzania równości).
- Wartości
null
iundefined
są sobie równe==
i nie są równe żadnej innej wartości. - Bądź ostrożny, gdy używasz porównań takich jak
>
lub<
ze zmiennymi, które mogą czasami byćnull/undefined
. Sprawdzanie dlanull/undefined
oddzielnie jest dobrym pomysłem.
.