Z matematiky známe mnoho porovnávacÃch operátorů.
V JavaScriptu se pÚà následovnÄ:
- VÄtÅ¡Ã/menšà než:
a > b,a < b. - VÄtÅ¡Ã/menšà nebo rovno:
a >= b,a <= b. - Rovno:
a == b. ProsÃme vÅ¡imnÄte si, že znak dvou rovnÃtek za sebou==znamená test rovnosti, zatÃmco jediné rovnÃtkoa = bznamená pÅiÅazenÃ. - Nerovno: v matematice se použÃvá znak
â, ale v JavaScriptu se pÃÅ¡ea != b.
V tomto Älánku se dozvÃme vÃc o různých druzÃch porovnánà a o tom, jak s nimi JavaScript zacházÃ, vÄetnÄ důležitých zvláštnostÃ.
Na konci najdete recept, jak se vyhnout různým problémům způsobeným JavaScriptovými âvtÃpkyâ.
Výsledkem je typ boolean
Všechny porovnávacà operátory vracejà hodnotu typu boolean:
trueâ znamená âanoâ, âsprávnÄâ nebo âpravdaâ.falseâ znamená âneâ, ânesprávnÄâ nebo ânepravdaâ.
PÅÃklad:
alert( 2 > 1 ); // true (správnÄ)
alert( 2 == 1 ); // false (nesprávnÄ)
alert( 2 != 1 ); // true (správnÄ)
Výsledek porovnánà můžeme pÅiÅadit do promÄnné, stejnÄ jako každou jinou hodnotu:
let výsledek = 5 > 4; // pÅiÅadÃme výsledek porovnánÃ
alert( výsledek ); // true
Porovnávánà ÅetÄzců
Ke zjiÅ¡tÄnÃ, zda je jeden ÅetÄzec vÄtšà než jiný, JavaScript použÃvá tzv. âslovnÃkovéâ neboli âlexikografickéâ poÅadÃ.
Jinými slovy, ÅetÄzce se porovnávajà znak po znaku.
PÅÃklad:
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
Algoritmus pro porovnánà dvou ÅetÄzců je jednoduchý:
- Porovnej prvnà znak obou ÅetÄzců.
- Je-li prvnà znak prvnÃho ÅetÄzce vÄtšà (nebo menÅ¡Ã) než prvnà znak druhého ÅetÄzce, je prvnà ÅetÄzec vÄtšà (nebo menÅ¡Ã) než druhý. TÃm jsme hotovi.
- V opaÄném pÅÃpadÄ, tedy jsou-li prvnà znaky obou ÅetÄzců stejné, porovnej stejným způsobem druhé znaky.
- Tento proces opakuj, dokud nedojdeÅ¡ na konec nÄkterého z ÅetÄzců.
- MajÃ-li oba ÅetÄzce stejnou délku, jsou si rovny. V opaÄném pÅÃpadÄ je delšà ÅetÄzec vÄtÅ¡Ã.
Ve výše uvedených pÅÃkladech porovnánà 'Z' > 'A' dojde k výsledku hned v prvnÃm kroku.
Porovnánà ÅetÄzců "Glow" a "Glee" vÅ¡ak vyžaduje vÃce kroků, jelikož ÅetÄzce se porovnávajà znak po znaku:
Gje stejné jakoG.lje stejné jakol.oje vÄtšà neže. Tady se zastavÃme. Prvnà ÅetÄzec je vÄtÅ¡Ã.
Uvedený porovnávacà algoritmus zhruba odpovÃdá tomu, jaký se použÃvá k Åazenà ve slovnÃcÃch nebo telefonnÃch seznamech, ale nenà úplnÄ stejný.
NapÅÃklad záležà na velikosti pÃsmen. Velké pÃsmeno "A" nenà rovno malému "a". Které je vÄtÅ¡Ã? Malé "a". ProÄ? Protože malá pÃsmena majà v internà kódovacà tabulce, kterou JavaScript použÃvá (Unicode), vyššà index. Ke specifickým podrobnostem a důsledkům se vrátÃme v kapitole ÅetÄzce.
Porovnávánà rozdÃlných typů
Když JavaScript porovnává hodnoty různých typů, pÅevádà je na ÄÃsla.
PÅÃklad:
alert( '2' > 1 ); // true, ÅetÄzec '2' se pÅevede na ÄÃslo 2
alert( '01' == 1 ); // true, ÅetÄzec '01' se pÅevede na ÄÃslo 1
U hodnot typu boolean se true pÅevede na 1 a false na 0.
PÅÃklad:
alert( true == 1 ); // true
alert( false == 0 ); // true
Je možné, že souÄasnÄ:
- DvÄ hodnoty se budou rovnat.
- Jedna z nich bude jako boolean
truea druháfalse.
PÅÃklad:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
Z pohledu JavaScriptu je tento výsledek zcela normálnÃ. Test rovnosti pÅevádà hodnoty pomocà konverze na ÄÃsla (proto se "0" pÅevede na 0), zatÃmco explicitnà konverze Boolean funguje podle jiných pravidel.
Striktnà rovnost
BÄžné ovÄÅenà rovnosti == má problém. Nedokáže rozliÅ¡it 0 od false:
alert( 0 == false ); // true
Totéž platà pro prázdný ÅetÄzec:
alert( '' == false ); // true
To se dÄje proto, že operátor rovnosti == pÅevádà operandy různých typů na ÄÃsla. Prázdný ÅetÄzec, stejnÄ jako false, se pÅevede na nulu.
Co máme dÄlat, jestliže chceme rozliÅ¡it 0 od false?
Operátor striktnà rovnosti === zkontroluje rovnost bez typové konverze.
Jinými slovy, jsou-li a a b různých typů, pak a === b okamžitÄ vrátà false, aniž by se je pokusil konvertovat.
Zkusme to:
alert( 0 === false ); // false, protože typy jsou různé
Existuje i operátor âstriktnà nerovnostiâ !==, který je analogický s !=.
Operátor striktnà rovnosti se pÃÅ¡e troÅ¡iÄku déle, ale dÃky nÄmu je hned zÅejmé, o co tady jde, a ponechává ménÄ prostoru k chybám.
Porovnávánàs null a undefined
Chovánà pÅi porovnávánà null nebo undefined s jinými hodnotami nenà zcela intuitivnÃ.
- U operátoru striktnà rovnosti
=== -
Tyto hodnoty jsou různé, protože každá z nich je jiného typu.
alert( null === undefined ); // false - U operátoru nestriktnà rovnosti
== -
Platà zvláštnà pravidlo. Tyto dvÄ hodnoty tvoÅà âzamilovanou dvojiciâ: jsou si navzájem rovny (ve smyslu
==), ale nejsou rovny žádné jiné hodnotÄ.alert( null == undefined ); // true - U matematických a jiných porovnánÃ
< > <= >= -
null/undefinedse pÅevádÄjà na ÄÃsla:nullse pÅevede na0, zatÃmcoundefinedse pÅevede naNaN.
Nynà se podÃvejme na nÄkteré legraÄnà jevy, k nimž docházà pÅi použità tÄchto pravidel. A, což je důležitÄjÅ¡Ã, jak se s nimi nechytit do pasti.
Podivný výsledek: null vs 0
Porovnejme null s nulou:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
Matematicky je to zvláštnÃ. Poslednà uvedený výsledek tvrdÃ, že ânull je vÄtšà nebo rovno nuleâ, takže jedno z výše uvedených porovnánà musà být true, ale obÄ jsou false.
Důvodem je, že test rovnosti == a porovnánà > < >= <= fungujà odliÅ¡nÄ. Porovnánà pÅevedou null na ÄÃslo a zacházejà s nÃm jako s 0. Proto (3) null >= 0 platà a (1) null > 0 neplatÃ.
Naproti tomu rovnost == pro undefined a null je definována tak, že se bez jakýchkoli konverzà rovnajà navzájem a nerovnajà se niÄemu jinému. Proto (2) null == 0 neplatÃ.
Neporovnatelné undefined
Hodnota undefined by nemÄla být porovnávána s jinými hodnotami:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
ProÄ ji porovnávánà nemá tak rádo? Vždycky vyjde false!
Tyto výsledky jsme zÃskali, protože:
- PorovnánÃ
(1)a(2)vracejÃfalse, protožeundefinedse pÅevede naNaNaNaNje speciálnà ÄÃselná hodnota, která pÅi vÅ¡ech porovnánÃch vrátÃfalse. - Test rovnosti
(3)vracÃfalse, protožeundefinedse rovná jedinÄnullaundefined, žádné jiné hodnotÄ.
Jak se vyhnout problémům
Jak se pÅes tyto pÅÃklady pÅenést? MÄli bychom si tyto zvláštnosti neustále pamatovat? VlastnÄ ani ne. Ve skuteÄnosti se s tÄmito triky postupem Äasu sžijete, ale existuje solidnà způsob, jak se vyhnout problémům, které způsobujÃ:
- Zacházejte s každým porovnánÃm s
undefined/nullkromÄ striktnà rovnosti===výjimeÄnÄ opatrnÄ. - NepoužÃvejte porovnánÃ
>= > < <=na promÄnnou, která by mohla býtnull/undefined, pokud si opravdu nejste jisti tÃm, co dÄláte. Může-li promÄnná obsahovat tyto hodnoty, ovÄÅte je zvlášť.
ShrnutÃ
- Porovnávacà operátory vracejà hodnotu typu boolean.
- ÅetÄzce se porovnávajà znak po znaku podle âslovnÃkovéhoâ poÅadÃ.
- Když se porovnávajà hodnoty různých typů, pÅevedou se na ÄÃsla (s výjimkou operátoru striktnà rovnosti).
- Hodnoty
nullaundefinedse rovnajÃ==sobÄ navzájem, ale nerovnajà se žádné jiné hodnotÄ. - BuÄte opatrnà pÅi použÃvánà porovnávánà jako
<nebo>na promÄnné, které mohou býtnull/undefined. Dobrý nápad je oddÄlenÄ ovÄÅit, zda opravdu jsounull/undefined.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)