Porównania

author
6 minutes, 46 seconds Read

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 pojedynczy a = b oznacza przyporządkowanie.
  • Nie równe. W matematyce jest to , ale w JavaScript zapisuje się to jako a != 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:

  1. Porównaj pierwszy znak obu ciągów.
  2. 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.
  3. W przeciwnym razie, jeśli pierwsze znaki obu ciągów są takie same, porównaj drugie znaki w ten sam sposób.
  4. Powtarzaj aż do końca jednego z ciągów.
  5. 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:

  1. G jest taki sam jak G.
  2. l jest taki sam jak l.
  3. o jest większy niż e. Zatrzymaj się tutaj. Pierwszy ciąg jest większy.
Nie prawdziwy słownik, ale porządek Unicode

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

Zabawna konsekwencja

Możliwe jest, że w tym samym czasie:

  • Dwie wartości są równe.
  • Jedna z nich to true jako boolean, a druga to false 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 na NaN, a NaN jest specjalną wartością liczbową, która zwraca false dla wszystkich porównań.
  • Sprawdzanie równości (3) zwraca false, ponieważ undefined jest równe tylko null, 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 i undefined 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 dla null/undefined oddzielnie jest dobrym pomysłem.

.

Similar Posts

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.