4 min read

Az operátorok - utolsó rész

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