Tunnemme matematiikasta monia vertailuoperaattoreita.
Javaskriptissä ne kirjoitetaan näin:
- Suurempi/vähemmän kuin:
a > b
,a < b
. - Greater/less than tai equals:
a >= b
,a <= b
. - Vastaavat:
a >= b
,a <= b
. - Vastaavat:
a == b
, huomaa kaksinkertainen yhtäläisyysmerkki==
tarkoittaa yhtäläisyystestiä, kun taas yksittäinena = b
tarkoittaa osoitusta. - Ei yhtäläinen. Matematiikassa merkintätapa on
≠
, mutta JavaScriptissä se kirjoitetaana != b
.
Tässä artikkelissa opimme lisää erityyppisistä vertailuista ja siitä, miten JavaScript tekee niitä, mukaan lukien tärkeät erityispiirteet.
Lopusta löydät hyvän reseptin, jolla voit välttää ”JavaScriptin omituisuuksiin” liittyviä ongelmia.
Boolean on tulos
Kaikki vertailuoperaattorit palauttavat boolean-arvon:
-
true
– tarkoittaa ”kyllä”, ”oikein” tai ”totuus”. -
false
– tarkoittaa ”ei”, ”väärin” tai ”ei totuus”.
Esimerkiksi:
alert( 2 > 1 ); // true (correct)alert( 2 == 1 ); // false (wrong)alert( 2 != 1 ); // true (correct)
Vertailutulos voidaan osoittaa muuttujaan, kuten mikä tahansa arvo:
let result = 5 > 4; // assign the result of the comparisonalert( result ); // true
merkkijonojen vertailu
Katsoakseen, onko jokin merkkijono suurempi kuin jokin toinen, JavaScript käyttää niin sanottua sanakirjamaista tai leksikografista järjestystä.
Toisin sanoen merkkijonoja verrataan kirjain kirjaimelta.
Esimerkiksi:
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
Algoritmi, jolla verrataan kahta merkkijonoa keskenään, on yksinkertainen:
- Vertaile molempien merkkien ensimmäistä merkkiä.
- Jos ensimmäisen merkkijonon ensimmäinen merkki on suurempi (tai pienempi) kuin toisen merkkijonon merkki, niin ensimmäinen merkkijono on suurempi (tai pienempi) kuin toinen. Olemme valmiit.
- Muussa tapauksessa, jos molempien merkkijonojen ensimmäiset merkit ovat samat, verrataan toista merkkiä samalla tavalla.
- Vertaillaan, kunnes jompikumpi merkkijono loppuu.
- Jos molempien merkkijonojen loppu on samanpituinen, ne ovat yhtä pitkät. Muussa tapauksessa pidempi merkkijono on suurempi.
Yllä olevassa ensimmäisessä esimerkissä vertailu 'Z' > 'A'
pääsee tulokseen jo ensimmäisessä vaiheessa.
Toisessa vertailussa 'Glow'
ja 'Glee'
tarvitaan useampia vaiheita, koska merkkijonoja verrataan merkeittäin:
-
G
on sama kuinG
. -
l
on sama kuinl
. -
o
on suurempi kuine
. Lopeta tähän. Ensimmäinen merkkijono on suurempi.
Yllä esitetty vertailualgoritmi vastaa suurin piirtein sanakirjoissa tai puhelinluetteloissa käytettävää algoritmia, mutta se ei ole täsmälleen sama.
Esimerkiksi isolla ja pienellä kirjaimella on merkitystä. Iso kirjain "A"
ei ole sama kuin pieni kirjain "a"
. Kumpi on suurempi? Pienaakkoset "a"
. Miksi? Koska pienellä kirjaimella on suurempi indeksi JavaScriptin käyttämässä sisäisessä koodaustaulukossa (Unicode). Palaamme tämän tarkempiin yksityiskohtiin ja seurauksiin luvussa Merkkijonot.
Erttyyppisten arvojen vertailu
Erttyyppisiä arvoja vertailtaessa JavaScript muuntaa arvot numeroiksi.
Esimerkiksi:
alert( '2' > 1 ); // true, string '2' becomes a number 2alert( '01' == 1 ); // true, string '01' becomes a number 1
Boolen arvojen osalta true
muuttuu 1
:ksi 1
:ksi ja false
muuttuu 0
:ksi.
Esimerkiksi:
alert( true == 1 ); // truealert( false == 0 ); // true
Mahdollista on, että samanaikaisesti:
- Kaksi arvoa on yhtä suuri.
- Toinen niistä on
true
boolean-arvona ja toinenfalse
boolean-arvona.
Esimerkiksi:
let a = 0;alert( Boolean(a) ); // falselet b = "0";alert( Boolean(b) ); // truealert(a == b); // true!
Javaskriptin kannalta tämä lopputulos on aivan normaali. Yhdenvertaisuustarkistus muuntaa arvot käyttämällä numeerista muunnosta (joten "0"
muuttuu 0
), kun taas eksplisiittinen Boolean
-muunnos käyttää toista sääntöjoukkoa.
Tarkka yhdenvertaisuus
Säännöllisessä yhdenvertaisuustarkistuksessa ==
on ongelma. Se ei pysty erottamaan 0
:tä false
:stä:
alert( 0 == false ); // true
Samoin käy tyhjän merkkijonon kanssa:
alert( '' == false ); // true
Tämä tapahtuu, koska erityyppiset operandit muunnetaan luvuiksi tasa-arvooperaattorilla ==
. Tyhjä merkkijono, aivan kuten false
, muuttuu nollaksi.
Mitä tehdään, jos halutaan erottaa 0
ja false
toisistaan?
Tarkka tasa-arvo-operaattori ===
tarkistaa tasa-arvon ilman tyyppimuunnosta.
Muuten sanoen, jos a
ja b
ovat eri tyyppisiä, niin a === b
palauttaa välittömästi false
yrittämättä muuntaa niitä.
Kokeillaan:
alert( 0 === false ); // false, because the types are different
On olemassa myös ”tiukka epätasa-arvo” -operaattori !==
, joka on analoginen operaattorin !=
kanssa.
Tarkka tasa-arvo-operaattori on hieman pidempi kirjoittaa, mutta tekee selväksi, mistä on kyse, ja jättää vähemmän tilaa virheille.
Vertailu nollaan ja määrittelemättömään
On olemassa ei-intuitiivinen käyttäytyminen, kun null
tai undefined
verrataan muihin arvoihin.
Tiukassa tasa-arvotarkastuksessa===
Nämä arvot ovat erilaisia, koska kumpikin niistä on eri tyyppiä.
alert( null === undefined ); // false
Ei-striktiotarkastuksessa==
Tässä on erikoissääntö. Nämä kaksi ovat ”suloinen pari”: ne ovat yhtä suuret keskenään (==
merkityksessä), mutta eivät mitään muuta arvoa.
alert( null == undefined ); // true
Matematiikkaa ja muita vertailuja varten< > <= >=
null/undefined
muunnetaan numeroiksi: null
muuttuu 0
:ksi, kun taas undefined
muuttuu NaN
:ksi.
Katsotaan nyt hauskoja asioita, joita tapahtuu, kun sovellamme näitä sääntöjä. Ja, mikä tärkeämpää, miten emme joudu niiden avulla ansaan.
Omituinen tulos: nolla vs. 0
Vertaillaan null
nollaan:
alert( null > 0 ); // (1) falsealert( null == 0 ); // (2) falsealert( null >= 0 ); // (3) true
Matemaattisesti katsottuna tuo on outoa. Viimeisessä tuloksessa todetaan, että ”null
on suurempi tai yhtä suuri kuin nolla”, joten jommassakummassa yllä olevassa vertailussa sen täytyy olla true
, mutta molemmat ovat vääriä.
Syy on se, että tasa-arvotarkistus ==
ja vertailut > < >= <=
toimivat eri tavalla. Vertailut muuttavat null
luvuksi, jolloin sitä käsitellään 0
:nä. Siksi (3) null >= 0
on tosi ja (1) null > 0
on epätosi.
Toisaalta yhtäläisyystarkistus ==
undefined
:lle ja null
:lle on määritelty siten, että ilman muunnoksia ne ovat yhtä suuret keskenään eivätkä ole yhtä suuria kuin mikään muu. Siksi (2) null == 0
on väärä.
Vertailematon määrittelemätön
Arvoa undefined
ei saa verrata muihin arvoihin:
alert( undefined > 0 ); // false (1)alert( undefined < 0 ); // false (2)alert( undefined == 0 ); // false (3)
Miksi se inhoaa nollaa niin paljon? Aina väärä!
Saamme nämä tulokset, koska:
- Vertailut
(1)
ja(2)
palauttavatfalse
, koskaundefined
muunnetaanNaN
:ksi jaNaN
on erikoisnumeerinen arvo, joka palauttaafalse
kaikissa vertailuissa. - Yhtäläisyystarkistus
(3)
palauttaafalse
, koskaundefined
on yhtä kuinnull
,undefined
eikä mikään muu arvo.
Välttää ongelmia
Miksi kävimme läpi nämä esimerkit? Pitäisikö meidän muistaa nämä erityispiirteet koko ajan? No, ei oikeastaan. Itse asiassa nämä hankalat asiat tulevat ajan myötä vähitellen tutuiksi, mutta on olemassa vankka tapa välttää ongelmia niiden kanssa:
- Käsittele kaikkia vertailuja
undefined/null
:n kanssa, lukuun ottamatta tiukkaa yhtäläisyyttä===
, poikkeuksellisen varovaisesti. - Älä käytä vertailuja
>= > < <=
muuttujan kanssa, joka voi ollanull/undefined
, ellet ole todella varma, mitä olet tekemässä. Jos muuttujalla voi olla näitä arvoja, tarkista ne erikseen.
Yhteenveto
- Vertailuoperaattorit palauttavat boolean-arvon.
- Stringejä verrataan kirjain kirjaimelta ”sanakirja”-järjestyksessä.
- Kun erityyppisiä arvoja verrataan, ne muunnetaan numeroiksi (poislukien tiukka tasa-arvotarkistus).
- Arvot
null
jaundefined
ovat yhtä suuria==
keskenään eivätkä ole yhtä suuria minkään muun arvon kanssa. - Ole varovainen käyttäessäsi vertailuoperaattoreita, kuten
>
tai<
, muuttujien kanssa, jotka voivat toisinaan ollanull/undefined
.null/undefined
:n tarkistaminen erikseen on hyvä idea.