Espressioni Logiche in JavaScript
- Gli operatori logici in JavaScript sono utilizzati per combinare valori booleani e restituire un risultato booleano.
- Gli operatori
&&
,||
, e!
eseguono operazioni di algebra booleana. - Gli operatori logici sono spesso utilizzati in combinazione con gli operatori relazionali per creare espressioni più complesse.
Espressioni Logiche
Gli operatori logici &&
, ||
, e !
eseguono operazioni di algebra booleana e sono spesso utilizzati in combinazione con gli operatori relazionali per combinare due espressioni relazionali in un'unica espressione più complessa. Questi operatori sono descritti nelle sottosezioni che seguono.
AND Logico
L'operatore &&
può essere compreso a tre livelli diversi. Al livello più semplice, quando utilizzato con operandi booleani, &&
esegue l'operazione Boolean AND sui due valori: restituisce true
se e solo se sia il suo primo operando che il suo secondo operando sono true
. Se uno o entrambi questi operandi sono false
, restituisce false
.
&&
è spesso usato come congiunzione per unire due espressioni relazionali:
x === 0 && y === 0 // true se, e solo se, x e y sono entrambi 0
Le espressioni relazionali valutano sempre a true
o false
, quindi quando usato in questo modo, l'operatore &&
stesso restituisce true
o false
. Gli operatori relazionali hanno precedenza più alta di &&
(e ||
), quindi espressioni come queste possono essere scritte in sicurezza senza parentesi.
Ma &&
non richiede che i suoi operandi siano valori booleani. Ricordiamo che tutti i valori JavaScript sono o "truthy" o "falsy". I valori falsy sono false
, null
, undefined
, 0
, -0
, NaN
, e ""
. Tutti gli altri valori, inclusi tutti gli oggetti, sono truthy. Il secondo livello al quale &&
può essere compreso è come operatore Boolean AND per valori truthy e falsy. Se entrambi gli operandi sono truthy, l'operatore restituisce un valore truthy. Altrimenti, uno o entrambi gli operandi devono essere falsy, e l'operatore restituisce un valore falsy. In JavaScript, qualsiasi espressione o statement che si aspetta un valore booleano funzionerà con un valore truthy o falsy, quindi il fatto che &&
non restituisca sempre true
o false
non causa problemi pratici.
Notare che questa descrizione dice che l'operatore restituisce "un valore truthy" o "un valore falsy" ma non specifica quale sia quel valore. Per quello, dobbiamo descrivere &&
al terzo e ultimo livello. Questo operatore inizia valutando il suo primo operando, l'espressione alla sua sinistra. Se il valore a sinistra è falsy, il valore dell'intera espressione deve essere anch'esso falsy, quindi &&
semplicemente restituisce il valore a sinistra e non valuta nemmeno l'espressione a destra.
D'altra parte, se il valore a sinistra è truthy, allora il valore complessivo dell'espressione dipende dal valore sul lato destro. Se il valore a destra è truthy, allora il valore complessivo deve essere truthy, e se il valore a destra è falsy, allora il valore complessivo deve essere falsy. Quindi quando il valore a sinistra è truthy, l'operatore &&
valuta e restituisce il valore a destra:
let o = {x: 1};
let p = null;
o && o.x // => 1: o è truthy, quindi restituisce il valore di o.x
p && p.x // => null: p è falsy, quindi lo restituisce e non valuta p.x
È importante comprendere che &&
può o non può valutare il suo operando destro. In questo esempio di codice, la variabile p
è impostata a null
, e l'espressione p.x
causerebbe, se valutata, un TypeError. Ma il codice usa &&
in modo idiomatico così che p.x
viene valutata solo se p
è truthy---non null
o undefined
.
Il comportamento di &&
è talvolta chiamato cortocircuito, e a volte potresti vedere codice che sfrutta deliberatamente questo comportamento per eseguire codice condizionalmente. Ad esempio, le seguenti due righe di codice JavaScript hanno effetti equivalenti:
if (a === b) stop(); // Invoca stop() solo se a === b
(a === b) && stop(); // Questo fa la stessa cosa
In generale, devi essere attento ogni volta che scrivi un'espressione con effetti collaterali (assegnazioni, incrementi, decrementi, o invocazioni di funzioni) sul lato destro di &&
. Se quegli effetti collaterali si verificano dipende dal valore del lato sinistro.
Nonostante il modo piuttosto complesso in cui questo operatore effettivamente funziona, è più comunemente usato come un semplice operatore di algebra booleana che lavora su valori truthy e falsy.
OR Logico
L'operatore ||
esegue l'operazione OR booleana sui suoi due operandi. Se uno o entrambi gli operandi sono truthy, restituisce un valore truthy. Se entrambi gli operandi sono falsy, restituisce un valore falsy.
Sebbene l'operatore ||
sia utilizzato più spesso semplicemente come operatore OR booleano, esso, come l'operatore &&
, ha un comportamento più complesso. Inizia valutando il suo primo operando, l'espressione alla sua sinistra. Se il valore di questo primo operando è truthy, fa short-circuit e restituisce quel valore truthy senza mai valutare l'espressione a destra. Se, d'altra parte, il valore del primo operando è falsy, allora ||
valuta il suo secondo operando e restituisce il valore di quell'espressione.
Come con l'operatore &&
, dovremmo evitare operandi del lato destro che includano effetti collaterali, a meno che non vogliamo intenzionalmente utilizzare il fatto che l'espressione del lato destro potrebbe non essere valutata.
Un uso idiomatico di questo operatore è selezionare il primo valore truthy in un insieme di alternative
// Se larghezzaMassima è truthy, usa quello. Altrimenti, cerca un valore nell'
// oggetto preferenze. Se quello non è truthy, usa una costante hardcoded.
let massimo = larghezzaMassima || preferenze.larghezzaMassima || 500;
Si noti che se 0 è un valore legale per larghezzaMassima
, allora questo codice non funzionerà correttamente, poiché 0 è un valore falsy.
Prima di ES6, questo idioma è spesso utilizzato nelle funzioni per fornire valori predefiniti per i parametri:
// Copia le proprietà di o in p, e restituisce p
function copia(o, p) {
p = p || {}; // Se nessun oggetto passato per p, usa un oggetto appena creato.
// il corpo della funzione va qui
}
In ES6 e successivi, tuttavia, questo trucco non è più necessario perché il valore del parametro predefinito potrebbe essere semplicemente scritto nella definizione della funzione stessa: function copia(o, p={}) { ... }
.
NOT Logico
L'operatore !
è un operatore unario; viene posizionato prima di un singolo operando. Il suo scopo è invertire il valore booleano del suo operando. Ad esempio, se x
è truthy, !x
valuta a false
. Se x
è falsy, allora !x
è true
.
A differenza degli operatori &&
e ||
, l'operatore !
converte il suo operando in un valore booleano (usando le regole descritte nel Capitolo 3) prima di invertire il valore convertito. Questo significa che !
restituisce sempre true
o false
e che è possibile convertire qualsiasi valore x
nel suo valore booleano equivalente applicando questo operatore due volte: !!x
.
Come operatore unario, !
ha alta precedenza e si lega strettamente. Se si vuole invertire il valore di un'espressione come p && q
, è necessario usare le parentesi: !(p && q)
. Vale la pena notare qui due leggi dell'algebra booleana che possiamo esprimere usando la sintassi JavaScript:
// Leggi di DeMorgan
!(p && q) === (!p || !q) // => true: per tutti i valori di p e q
!(p || q) === (!p && !q) // => true: per tutti i valori di p e q