JavaScript logički operatori
Upoznali smo se sa relacionim operatorima koji predstavljaju upoređivanja. Pomoću njih kreiramo bazične uslove. Međutim, bilo kakav složeniji uslov zahteva povezivanje bazičnih uslova logičkim operatorima.
Operator | Primer | Asocijativnost |
---|---|---|
Logička negacija | !x | ulevo |
Logička konjukcija | x && y | udesno |
Logička disjunkcija | x || y | udesno |
Sećamo se problema koji smo imali u tekstu o Relacionim operatorima kada smo želeli da napravimo kompleksan uslov - npr. da proverimo da li je vrednost neke promenljive između dva broja? Pokazalo se da to ne možemo da uradimo na način na koji smo navikli u matematici:
10 < x < 15 // neispravno!
- prvo se upoređuje broj 10 sa promenljivom x
- rezultat tog upoređivanja će biti logička vrednost (true ili false)
- onda se ta logička vrednost upoređuje sa brojem 15
- ako je false računa se kao 0, a true kao 1 - svejedno, oba su manja od 15 i lako dobijamo netačan rezultat
Nikada ne zaboravite da su u pitanju operatori koji povezuju dva operanda tzv. binarni operatori (ovo "binarni" ovde nema veze sa binarnim brojevima). To znači da uvek treba da razmišljamo u okviru "dva-po-dva", odnosno da ovi operatori treba da povežu dve vrednosti. U stvari moramo da kreiramo kompleksan uslov koji će povezati dva bazična uslova: da je x veće od 10 i istovremeno da je x manje od 15. Ova veza se ostvaruje operatorom logičke konjukcije (logičko I) koji zahteva da oba uslova koja povezuje budu zadovoljena.
(x > 10) && (x < 15)
Logički operatori su:
!U | negacija uslova - efektivno obrće vrednost uslova |
U1 && U2 | logička konjukcija (logičko I) - vraća vrednost tačno ako su oba uslova zadovoljena |
U1 || U2 | logička disjunkcija (logičko ILI) - vraća vrednost tačno ako je bar jedan uslov zadovoljen |
Da se podsetimo matematičke tautologije. Logička negacija je unarna operacija i služi da "obrne" zadati uslov:
a | !a |
---|---|
F | T |
T | F |
Logičko "I" je operacija koja zahteva da oba uslova budu zadovoljena:
a | b | a && b |
---|---|---|
F | F | F |
F | T | F |
T | F | F |
T | T | T |
Za operaciju "ILI" važi sledeća tablica tautologije:
a | b | a || b |
---|---|---|
F | F | F |
F | T | T |
T | F | T |
T | T | T |
Logičke operacije
Ove operacije najčešće koristimo kako bismo napravili uslov za dalje izvršavanje programa.
if (!(x < 10)) {
console.log("X nije manje od 10.");
}
if ((x > 10) && (x < 15)) {
console.log("X veće od 10 i istovremeno manje od 15.");
}
if ((x == 10) || (x == 20) || (x == 30)) {
console.log("X jednako 10, 20 ili 30.");
}
Hmmm, ako smo rekli da ovi operatori povezuju dve vrednosti, kako to u poslednjem primeru imamo tri povezana uslova? Pa jednostavno, uvek se svodi na upoređivanje dva i dva. Prvo se ispita disjunkcija između prva dva upoređivanja: da li je X možda 10 ili 20. Rezultat toga je vrednost "tačno" ili "netačno". Ova vrednost se onda povezuje sa trećim uslovom i dobijamo finalni rezultat.
Tako je u teoriji. U "pravom životu", se ne dešava sve baš ovako, zbog skraćene evaluacije. Čitajte dalje.
Skraćena evaluacija
JavaScript radi tzv. skraćenu evaluaciju kompleksnih logičkih uslova. To suštinski znači - provera uslova se prekida onog trenutka kada se sa sigurnošću utvrdi vrednost.
Sećate se da smo rekli da će rezultat logičke konjukcije (logičko I, odnosno &&) vratiti vrednost true samo u slučaju da su obe (tačnije sve povezane) logičke vrednosti true. Drugim rečima, čim se naiđe na false, prekida se ispitivanje uslova - prosto više nema smisla proveravati.
true && true && false && nebitno
Potpuno ista stvar važi i za logički disjunkciju (logičko ili, odnosno operator ||). Rezultat će biti true ako je makar jedan od povezanih uslova true. To znači da kada se pri proveri kompleksnog logičkog izraza povezanog operatorom || naiđe na neki uslov koji je true, prekida se dalja provera, pošto će rezultat do kraja sigurno biti true, pa nema svrhe dalje raditi.
false || false || true || nebitno
Ovo je bitna optimizacija sa stanovišta brzine izvršavanja programa. Na prvi pogled nam se čini da sve to ima savršenog smisla i da nikako drugačije i ne treba da se radi. Ipak, ova stvar može da nam zasmeta u situacijama kada logičkim operatorima povezujemo funkcije koje vraćaju vrednost.
Skraćena evaluacija
Evo jednog prostog primera kako biste videli moguće posledice skraćene evaluacije.
var x = 20;
var br = 0;
// funkcija uporedi upoređuje globalnu promenljivu X sa zadatim brojem NUM
function uporedi(num) {
br++; // povećava brojač izvršenih poređenja
return (x == num); // vraća TRUE ako je X jednako NUM
}
if (uporedi(10) || uporedi(20) || uporedi(30)) {
console.log("X jednako 10, 20 ili 30.");
console.log(br); // broj poređenja je samo 2 (ne 3 kako bismo očekivali)
}
Pošto x ima vrednost 20, izvršiće se prvo poređenje (sa brojem 10) i njegova vrednost će biti false. Onda ide drugo poređenje (sa brojem 20) i njegova vrednost je true. Treće poređenje se ne vrši - zašto bi, kada smo već dobili true i znamo da će to biti finalni rezultat, kakav god bio rezultat poslednjeg poređenja.
Opasnost postoji u smislu da računamo na uzgredne efekte izvršenja funkcije. Dakle, zbog nečega nam je važno da se funkcija izvrši jer će uraditi još nešto osim što vraća rezultat (u ovom slučaju povećava brojač).