Az operátorok - utolsó rész
Gonosz módon operátorok kapcsán direkt csatoltam a címhez az első rész és utolsó rész utótagot, de nem lövöm le a poént, később vissza fogok erre utalni.
Comparison operators
Összehasonlító operátorok, melyek összehasonlítják az operandusokat és visszaadnak egy logikai értéket (true/false azaz igaz vagy hamis) az összehasonlítás eredményétől függően. És akkor itt is bejön a képbe az előző részben megismert automatikus típuskonverzió: ha a két operandus melyet szeretnénk összehasonlítani nem azonos típusúak, akkor a nyelv megcsinalája nekünk a konverziót, hacsak külön nem kérjük, hogy ne tegye (strict comparison). Nézzük az operátorokat ebben a csoportban:
- Equal (==): a visszaadott érték true ha a két operandus egyenlő.
Példa:
3 == "3"
Ugyanez változókkal:
var x = 3
var y = "3"
x == y - Not equal (!=): a visszaadott érték true ha a két operandus nem egyenlő.
Példa:
3 != 4 - Strict equal (===): a visszaadott érték true ha a két operandus egyenlő és azonos típusú
- Strict not equal (!==): a visszaadott érték true ha a két operandus nem egyenlő és/vagy a típusuk nem egyezik
- Greater than (>), greater than or equal (>=), less than (<), less than or equal (<=): a matematikából ismert nagyobb mint, nagyobb vagy egyenlő, kisebb mint és kisebb vagy egyenlő összehasonlítások.
Érdemes megemlíteni, hogy vannak nyelvek (pl. PHP) ahol a nagyobb és kisebb jelek kombinációjával (<>) jelölik a not equal-t.
Bitwise operators
A bitműveletek részben megismertük a logikai (logical) és eltoló (shift) műveleteket. Ezekre a javascriptben vannak operátorok is és hatásukra a bitműveleteknél leírtak fognak történni, itt nem ismétlem meg újra:
- AND (&): formája operand & operand
- OR (|): formája operand | operand
- XOR (^): formája operand ^ operand
- NOT (~): formája ~operand
- Left shift (<<): x << y (x-et tolja el balra y-szor, jobbról nullák jönnek be)
- Sign-propagating right shift (>>): előjeles jobbra tolás
- Zero-fill right shift (>>>): előjel nélküli jobbra tolás (0 kerül be balról, nem tartjuk meg az előjel bitet)
Logical operators
A logikai operátorokat legtöbbször boolean értékekkel (true/false) szokták használni és ezáltal kiválóak az összehasonlító operátorok összefűzésére, de ez nem kitétel.
- AND (&&): formája operand && operand. Ha a mindkét operandus boolean típusú, akkor a visszaadott érték true ha mindkét operandus true, egyébként pedig false a visszaadott érték. Egyéb esetben pedig visszaadja az első operandust ha az átkonvertálható false-ra, egyébként a második operandust adja vissza.
- OR (||): formája operand || operand. Ha a mindkét operandus boolean típusú, akkor a visszaadott érték true ha a két operandus bármelyike true vagy false ha mindkét operandus false. Egyéb esetben pedig visszaadja az első operandust ha az átkonvertálható true-ra, egyébként a második operandust adja vissza.
- NOT (!): formája !operand. False-t ad vissza ha az operandus átkonvertálható true-ra, egyébként pedig true-t.
Arról, hogy melyik érték hogyan konvertálódik true-ra vagy false-ra a későbbiekben még lesz szó.
Relational operators
Ezek az operátorok az összehasonlító operátorok speciális fajtái, melyek ugyanúgy boolean-t adnak vissza:
- in: a visszaadott érték true ha a vizsgált propery-t tartalmazza a vizsgált object. Szintakszisa: porperty in object. Használatára később fogok példát mutatni amikor a nyelvbe épített object-ekkel ismerkedünk.
- instanceof: a visszaadott érték true ha a vizsgált object típusa megegyezik a vizsgált object típussal. Szintakszisa: object instanceof objectType. Használatára szintén később fogok példát mutatni.
Comma operator (,)
Utoljára hagytam a , operátort, melyel kifejezéseket választunk el egymástól, ahol is ezek a kifejezések kiértékelődnek (balról jobbra), majd az utolsó kifejezés értékét adja vissza. Használata csak igen ritkán ajánlott, a több különálló kifejezés használata javasolt helyette.
Az operátorok precedenciája (sorrendje)
Csakúgy mint a matematikában a műveleteknek, az operátoroknak is van végrehajtási sorrendjük.
Operátor típus | Operátorok |
---|---|
negálás/növelés/csökkentés | ! ~ - + ++ -- typeof void delete |
szorzás/osztás | * / % |
összeadás/kivonás | + - |
bit eltolás | << >> >>> |
relációs | < <= > >= in instanceof |
egyenlőség | == != === !== |
bit and | & |
bit xor | ^ |
bit or | | |
logikai and | && |
logikai or | || |
ternary | ?: |
hozzárendelés |
= += -= *= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??=
|
vessző | , |
Az operátorok láncolása és az asszociativitás
Ha operátorokat láncolunk egymáshoz, akkor azok kiértékelése a precedencia táblázat sorrendjében történik. Ha két azonos precedenciaszinten álló operátort láncolunk, akkor jön képbe az asszociativitás. Ha esetleg ez a matematikai fogalom feledésbe merült volna az évek alatt, akkor itt az ideje, hogy tegyél egy kis kitérőt matematika földön.
Most, hogy visszajöttél a wikipédiáról és már annyit sem értesz belőle mint azelőtt, leegyszerüsítem neked: ha nem vagy benne biztos, hogy egy komplex programsornál milyen sorrendben értékelődnek ki az egyes részek (left to right vagy right-to-left), akkor:
- teszteld le és higgy a saját szemednek
- zárójelezd be, mint ahogy matekból megtanultad
Szóval teljesen felesleges táblázatokat magolni, ezek előbb-utóbb úgyis rögzülnek, amíg meg nincs meg ez a biztos tudás, addig ki kell próbálni és akkor nem hibázol.
Rövidzárlat
Ezt a kifejezést (short-circuit) a logikai kifejezések kapcsán érdemes megtanulni. Ha feltételvizsgálat kapcsán:
- logikai és (AND: &&) műveletet hajtunk végre, akkor ha az első operandusunk false, akkor teljesen mindegy, hogy a második operandusunk mi (tehát nem kell kiértékelni, rövidre zártuk a vizsgálatot), mert false-t fog visszaadni
- logikai vagy (OR: ||) műveletet hajtunk végre, akkor ha az első operandusunk true, akkor teljesen mindegy, hogy a második operandusunk mi, mert true-t fog visszaadni
FONTOS: rövidzár esetén a kifejezésünk többi része ki sem fog értékelődni!
Példa:
var thisIsTrue = true;
var counter = 10;
var result = thisIsTrue || counter++ < 2 ? "It is true" : "It is false";
A result változó "It is true" lesz mivel a thisIsTrue true volt. Mivel a thisIsTrue true volt az || utáni rész nem értékelődött ki (ott növeltük volna a counter változó értékét) így a counter változónk 10 maradt.
Írjuk át picit, látszólag olyanra aminek semmi értelme (nem is nagyon van, de jól lehet vele demonstrálni a chaining-et és a short-circuit-ot):
var counter = 10;
var result = counter++ > 10 || counter++ > 10 ? "It is true" : "It is false";
Mi történik itt? A counter a ++ operátor hatására egyel nő, de mivel a post-incrementes formát használtuk 10-et ad vissza az relációs operátorunknak, így az az operátor false-t fog továbbítani (10 ugye nem nagyobb 10-nél, hanem egyenlő vele) az || operátornak, mint első operandus. Mivel az || operátor csak akkor zár rövidre, ha az első operandusa true ezért most meg kell néznie a második operandust is, ahhoz viszont előbb ki kell értékelnie. A counter értéke itt már 11, így ezt kapjuk az összehasonlításhoz (majd ezután nő egyel) ami nagyobb mint 10 tehát ez az operandus true lesz. Tehát a result felveszi az "It is true" stringet, míg a counter értéke 12 lesz.
Mit tanultál ebben a leckében?
- befejeztük az operátorok tárgyalását, innentől a legtöbb furcsa szimbólum értelmet nyer majd a kódban
- megismerted a precedencia, az asszociativitás és a rövidzár fogalmát