Λογικοί τελεστές
Οι λογικοί τελεστές μας επιτρέπουν να συνδυάζουμε πολλαπλές boolean τιμές ή εκφράσεις σύγκρισης, δημιουργώντας πιο σύνθετες συνθήκες. Το αποτέλεσμα μιας λογικής πράξης είναι πάντα true
ή false
. Οι τρεις βασικοί λογικοί τελεστές που δούμε αναλυτικότερα σε αυτή την ενότητα είναι το AND (&&
), το OR (||
) και το NOT (!
).
Τελεστής AND (&&
)
Ο λογικός τελεστής AND (&&
) χρησιμοποιείται για να συνδυάσει δύο ή περισσότερα expressions (συνθήκες). Το αποτέλεσμα του νέου expression είναι αληθές μόνο αν όλες οι συνθήκες που συνδυάζει είναι αληθής. Αν έστω και μία από τις συνθήκες είναι ψευδής, τότε ολόκληρη η έκφραση επιστρέφει false
.
Ας το φανταστούμε σαν ένα απλό κανόνα που μας έθεταν οι γονείς μας στην παιδική μας ηλικία: “Μπορείς να παίξεις έξω ΑΝ έχει ήλιο ΚΑΙ ΑΝ έχεις τελειώσει τα μαθήματά σου.” Αν οποιαδήποτε από τις δύο συνθήκες δεν ίσχυε (πχ., βρέχει ή δεν έχουμε τελειώσει τα μαθήματα), τότε δεν θα μπορούσαμε να παίξουμε έξω.
Πίνακας αληθείας του τελεστή &&
Συνθήκη 1 | Συνθήκη 2 | Αποτέλεσμα (Συνθήκη 1 && Συνθήκη 2) |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
Ας δούμε ένα απλό παράδειγμα με conditional statement (θα τα δούμε αναλυτικά σε επόμενο κεφάλαιο):
1const age = 20;
2const hasLicense = true;
3
4// Ελέγχουμε αν ένα άτομο μπορεί να οδηγήσει
5if (age >= 18 && hasLicense === true) {
6 console.log("Μπορείτε να οδηγήσετε!");
7} else {
8 console.log("Δεν μπορείτε να οδηγήσετε.");
9}
10
11const anotherAge = 16;
12const anotherHasLicense = true;
13
14if (anotherAge >= 18 && anotherHasLicense === true) {
15 console.log("Μπορείτε να οδηγήσετε!");
16} else {
17 console.log("Δεν μπορείτε να οδηγήσετε.");
18}
Μπορείτε να μαντέψετε τα μηνύματα που θα εμφανιστούν στην κονσόλα μας με το παραπάνω παράδειγμα;
Ας δούμε ακόμα ένα παράδειγμα με περισσότερες από δύο συνθήκες:
1let temperature = 25;
2let isSunny = true;
3let isWeekend = true;
4
5if (temperature > 20 && isSunny && isWeekend) {
6 console.log("Τέλεια μέρα για παραλία!");
7} else {
8 console.log("Ίσως όχι για παραλία σήμερα.");
9}
Μπορείτε να μαντέψετε ποιο από τα δύο μηνύματα θα εμφανιστεί στην κονσόλα μας και γιατί;
Τελεστής OR (||
)
Ο λογικός τελεστής OR (||
) χρησιμοποιείται για να συνδυάσει δύο ή περισσότερα expressions (συνθήκες). Το αποτέλεσμα των expression με ||
είναι αληθές αν έστω και μία από τις συνθήκες που συνδυάζει είναι αληθείς. Είναι ψευδής μόνο αν όλες οι συνθήκες είναι ψευδής.
Σε αντιστοιχία με νωρίτερα, ας δούμε για λίγο πως ο κανόνας από την προηγούμενη ενότητα θα μπορούσε να γίνει πιο ελαστικός: “Μπορείς να βγεις έξω για παγωτό ΑΝ έχεις τελειώσει τα μαθήματά σου Ή ΑΝ έχεις βοηθήσει στις δουλειές του σπιτιού.” Σε αυτή την περίπτωση αρκεί να κάναμε μόνο ένα από τα δύο ζητούμενα για να φάμε παγωτό.
Πίνακας αληθείας του τελεστή ||
Συνθήκη 1 | Συνθήκη 2 | Αποτέλεσμα (Συνθήκη 1 || Συνθήκη 2) |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
Ας δούμε ένα απλό παράδειγμα:
1let userRole = "admin";
2
3// Ελέγχουμε αν ο χρήστης είναι διαχειριστής ή συντάκτης
4if (userRole === "admin" || userRole === "editor") {
5 console.log("Έχετε δικαιώματα επεξεργασίας.");
6} else {
7 console.log("Δεν έχετε δικαιώματα επεξεργασίας.");
8}
9
10let isRaining = false;
11let isCold = false;
12let hasSnowed = true;
13
14if (isRaining || isCold || hasSnowed) {
15 console.log("Πάρτε ένα μπουφάν!");
16} else {
17 console.log("Ηλιόλουστη μέρα!");
18}
Ποια μηνύματα πιστεύετε ότι θα εμφανιστού στην κονσόλα μας όταν εκτελέσουμε το παραπάνω παράδειγμα;
Λογικό NOT (!
)
Ο τελεστής NOT (!
), γνωστός και ως τελεστής άρνησης, είναι ο πιο απλός από τους λογικούς τελεστές. Η λειτουργία του είναι να αντιστρέφει το αποτέλεσμα μιας έκφρασης. Αν η έκφραση είναι true
, την κάνει false
, και αν είναι false
, την κάνει true
.
Είναι σαν να λέμε: “Δεν είναι αλήθεια ότι…” ή “Το αντίθετο του…”.
Ας δούμε ένα απλό παράδειγμα με αντιστροφή.
let isLoggedIn = false;
// Το παρακάτω statement...
if (isLoggedIn) {
console.log("Έχετε ήδη συνδεθεί!");
} else {
console.log("Παρακαλώ συνδεθείτε για να συνεχίσετε.");
}
// ...παράγει το ίδιο αποτέλεσμα με αυτό το statement
if (!isLoggedIn) {
console.log("Παρακαλώ συνδεθείτε για να συνεχίσετε.");
} else {
console.log("Έχετε ήδη συνδεθεί!");
}
Short-circuit evaluation
Το short-circuit evaluation είναι ένα αρκετά σημαντικό χαρακτηριστικό των λογικών τελεστών &&
και ||
. Το χαρακτηριστικό αυτό επιτρέπει στην JavaScript να “παρακάμψει” το evaluation ολόκληρου του expression αν το αποτέλεσμα μπορεί να καθοριστεί από το πρώτο μέρος της (ή τα πρώτα μέρη της μέρος της αν μιλάμε για παραπάνω από δύο expressions).
Πώς Λειτουργεί:
- Με τον τελεστή
&&
: αν το πρώτο μέρος της έκφρασης είναιfalse
, τότε η JavaScript δεν θα αξιολογήσει το δεύτερο μέρος, γιατί γνωρίζει ήδη ότι το συνολικό αποτέλεσμα θα είναιfalse
(αφού για τον τελεστή AND, όλες οι συνθήκες θα πρέπει να είναι αληθείς). - Με τον τελεστή
||
: αν το πρώτο μέρος της έκφρασης είναιtrue
, τότε η JavaScript δεν θα αξιολογήσει το δεύτερο μέρος, γιατί γνωρίζει ήδη ότι το συνολικό αποτέλεσμα θα είναιtrue
(αφού για τον τελεστή OR, αρκεί μία συνθήκη να είναι αληθής).
Η κατανόηση του short-circuit evaluation είναι σημαντική για δύο βασικούς λόγους:
Αποφυγή σφαλμάτων: μπορούμε να εκμεταλευτούμε αυτή την ιδιότητα για να αποφύγουμε την εκτέλεση κώδικα που θα προκαλούσε σφάλμα. Για παράδειγμα, αν θέλουμε να αποκτήσουμε πρόσβαση σε μια ιδιότητα ενός αντικειμένου, αλλά δεν είμαστε σίγουροι αν το αντικείμενο υπάρχει (θα μιλήσουμε για αντικείμενα λεπτομερώς σε επόμενη ενότητα), θα έπρεπε ο κώδικάς μας να μοιάζει κάπως έτσι:
const user = null; // ο χρήστης δεν έχει οριστεί ακόμα
// ελέγχουμε πρώτα αν το user υπάρχει
if (user !== null && user.name) {
console.log("Όνομα χρήστη: " + user.name);
} else {
console.log("Το αντικείμενο χρήστη δεν βρέθηκε ή δεν έχει όνομα.");
}
Στο παραπάνω παράδειγμα, αν επιχειρούσαμε να εκτλέσουμε το expression στο δεξί μέρος του τελεστή &&
θα προέκτυπτε σφάλμα: Uncaught TypeError: Cannot read properties of null
και αυτό γιατί το null
δεν έχει ιδιότητα με το όνομα name
. Χάρις στην ιδιότητα των τελεστών &&
και ||
όμως, το expression αυτό δεν θα εκτελεστεί ποτέ γιατί το αποτέλεσμα μπορεί να καθοριστεί από το expression στα αριστερά του τελεστή &&
(πχ., user !== null
) που είναι ψευδές, άρα ότι και να ακολουθήσει δεν έχει κάνενα νόημα.
Βελτιστοποίηση κώδικα: Μπορούμε να γράψουμε πιο αποδοτικό κώδικα, καθώς αποφεύγουμε την εκτέλεση περιττών διεργασιών. Αν για παράδειγμα έχουμε μια συνθήκη με τελεστή &&
, το πρώτο μέρος τις οποίας είναι αρκετό για να καθορίσει το αποτέλεσμα, το δεύτερο μέρος (που μπορεί να είναι χρονοβόρο) παραλείπεται:
function χρονοβόραΔιεργασία() {
console.log("Εκτελώ μια χρονοβόρα λειτουργία...");
return true;
}
const condition1 = false;
if (condition1 && χρονοβόραΔιεργασία()) {
console.log("Το αποτέλεσμα είναι true.");
} else {
console.log("H χρονοβόρα διεργασία δεν εκτελέστηκε.");
}
Στο παραπάνω παράδειγμα, η συνάρτηση χρονοβόραΔιεργασία()
δεν θα εκτελεστεί ποτέ γιατί το αποτέλεσμα της συνθήκης μπορεί να καθοριστεί από το expression στο αριστερά του τελεστή &&
, κάτι που μας εξοικονομεί χρόνο και υπολογιστικούς πόρους κατά την εκτέλεση του προγραμματός μας.
“Truthy” και “falsy” τιμές
Μέχρι τώρα, είδαμε τους λογικούς τελεστές (&&
, ||
, !
) να λειτουργούν με boolean τιμές (true
ή false
) που ήταν αποτέλεσμα κάποιου expression με τελεστή σύγκρισης. Ωστόσο, στην JavaScript, αυτοί οι τελεστές έχουν μια πιο ευέλικτη συμπεριφορά όταν αντιμετωπίζουν μη-boolean τιμές. Αυτό οφείλεται στην έννοια των truthy και falsy τιμών.
Τι σημαίνει “truthy” και “falsy”;
Στην JavaScript, σχεδόν κάθε τιμή μπορεί να ερμηνευθεί ως true
ή false
σε ένα πλαίσιο όπου απαιτείται μια boolean τιμή (πχ., σε ένα if
statement ή όταν χρησιμοποιείται με λογικούς τελεστές).
“Falsy” τιμές είναι εκείνες που ερμηνεύονται ως
false
. Οι πιο κοινές είναι:false
,0
(ο αριθμός μηδέν),""
(το κενό string), και τα objectsnull
,undefined
καιNaN
.“Truthy” τιμές είναι όλες οι άλλες τιμές που δεν είναι “falsy”. Για παράδειγμα, οποιοσδήποτε μη-μηδενικός αριθμός (πχ.,
1
,-5
), οποιοδήποτε μη-κενό string (πχ.,"hello"
),true
, άδεια arrays ([]
) και άδεια αντικείμενα ({}
).
Evalutation “truthy” και “falsy” τιμών
Η βασική διαφορά μεταξύ των boolean και των “truthy”/“falsy” τιμών όταν χρησιμοποιούνται με τους τελεστές &&
και ||
είναι δεν επιστρέφουν απαραίτητα true
ή false
όταν γίνονται evaluate. Αντίθετα, οι τελεστές &&
και ||
επιστρέφουν μία από τις αρχικές τιμές των τελεστέων τους, ανάλογα με το short-circuit evaluation και το αν είναι “truthy” ή “falsy”. Πιο συγκεκριμένα, ισχύουν τα παρακάτω σενάρια:
value1 && value2
:- Αν το
value1
είναι “falsy”, επιστρέφει τοvalue1
. - Αν το
value1
είναι “truthy”, επιστρέφει τοvalue2
.
- Αν το
value1 || value2
:- Αν το
value1
είναι “truthy”, επιστρέφει τοvalue1
. - Αν το
value1
είναι “falsy”, επιστρέφει τοvalue2
.
- Αν το
Ας δούμε και ένα παράδειγμα με κώδικα. Τα επεξηγηματικά σχόλια θα μας βοηθήσουν να καταλάβουμε τι γίνεται σε κάθε σενάριο:
1// Ο χρήστης δεν πληκτρολόγησε όνομα
2let usernameInput = "";
3
4// Το "" είναι falsy, οπότε το displayName γίνεται "Guest"
5let displayName = usernameInput || "Guest";
6
7// Εμφανίζει: Welcome, Guest!
8console.log("Welcome, " + displayName + "!");
9
10// Ο χρήστης πληκτρολόγησε όνομα "Alice"
11let actualUsername = "Alice";
12
13// Το "Alice" είναι truthy, οπότε το anotherDisplayName γίνεται "Alice"
14let anotherDisplayName = actualUsername || "Guest";
15
16// Εμφανίζει: Welcome, Alice!
17console.log("Welcome, " + anotherDisplayName + "!");
Η κατανόηση του πώς οι λογικοί τελεστές χειρίζονται τις “truthy” και “falsy” τιμές είναι ένα πολύ δυνατό εργαλείο, ειδικά για την απλοποίηση κώδικα και τον καθορισμό προεπιλεγμένων τιμών χωρίς τη χρήση πολύπλοκων statements.