Espressioni Aritmetiche in JavaScript
- Gli operatori aritmetici in JavaScript sono utilizzati per eseguire calcoli matematici.
- Gli operatori di elevamento a potenza, moltiplicazione, divisione e sottrazione sono i più comuni.
- L'operatore di addizione può anche eseguire concatenazione di stringhe.
- Gli operatori unari e bitwise hanno regole di utilizzo specifiche.
Espressioni Aritmetiche
Questa sezione copre gli operatori che eseguono operazioni aritmetiche o altre manipolazioni numeriche sui loro operandi. Gli operatori di elevamento a potenza, moltiplicazione, divisione e sottrazione sono semplici e vengono trattati per primi. L'operatore di addizione ha una sottosezione a sé perché può anche eseguire concatenazione di stringhe e ha alcune regole di conversione di tipo insolite. Gli operatori unari e gli operatori bitwise sono anch'essi trattati in sottosezioni a sé.
La maggior parte di questi operatori aritmetici (eccetto come notato di seguito) può essere utilizzata con operandi BigInt
o con numeri regolari, purché non si mescolino i due tipi.
Gli operatori aritmetici di base sono **
(elevamento a potenza), *
(moltiplicazione), /
(divisione), %
(modulo: resto dopo la divisione), +
(addizione), e -
(sottrazione). Come notato, discuteremo l'operatore +
in una sezione a sé. Gli altri cinque operatori di base semplicemente valutano i loro operandi, convertono i valori in numeri se necessario, e poi calcolano la potenza, il prodotto, il quoziente, il resto, o la differenza. Gli operandi non numerici che non possono convertire in numeri si convertono nel valore NaN
. Se uno degli operandi è (o si converte in) NaN
, il risultato dell'operazione è (quasi sempre) NaN
.
L'operatore **
ha precedenza più alta di *
, /
, e %
(che a loro volta hanno precedenza più alta di +
e -
). A differenza degli altri operatori, **
lavora da destra a sinistra, quindi 2**2**3
è lo stesso di 2**8
, non 4**3
. C'è un'ambiguità naturale in espressioni come -3**2
. A seconda della precedenza relativa del meno unario e dell'elevamento a potenza, quell'espressione potrebbe significare (-3)**2
o -(3**2)
. Diversi linguaggi gestiscono questo diversamente, e piuttosto che prendere una posizione, JavaScript semplicemente rende un errore di sintassi omettere le parentesi in questo caso, forzandoci a scrivere un'espressione non ambigua. **
è il più nuovo operatore aritmetico di JavaScript: è stato aggiunto al linguaggio con ES2016. La funzione Math.pow()
è stata disponibile dalle prime versioni di JavaScript, tuttavia, e esegue esattamente la stessa operazione dell'operatore **
.
L'operatore /
divide il primo operando per il secondo. Se siamo abituati a linguaggi di programmazione che distinguono tra numeri interi e numeri in virgola mobile, potremmo aspettarci di ottenere un risultato intero quando dividiamo un intero per un altro. In JavaScript, tuttavia, tutti i numeri sono in virgola mobile, quindi tutte le operazioni di divisione hanno risultati in virgola mobile: 5/2
valuta a 2.5
, non 2
. La divisione per zero produce infinito positivo o negativo, mentre 0/0
valuta a NaN
: nessuno di questi casi solleva un errore.
L'operatore %
calcola il primo operando modulo il secondo operando. In altre parole, restituisce il resto dopo la divisione intera del primo operando per il secondo operando. Il segno del risultato è lo stesso del segno del primo operando. Per esempio, 5 % 2
valuta a 1
, e -5 % 2
valuta a -1
.
Mentre l'operatore modulo è tipicamente utilizzato con operandi interi, funziona anche per valori in virgola mobile. Per esempio, 6.5 % 2.1
valuta a 0.2
.
L'operatore di Addizione
L'operatore binario +
addiziona operandi numerici o concatena operandi stringa:
1 + 2 // => 3
"ciao" + " " + "mondo" // => "ciao mondo"
"1" + "2" // => "12"
Quando i valori di entrambi gli operandi sono numeri, o sono entrambi stringhe, è ovvio cosa fa l'operatore +
. In qualsiasi altro caso, tuttavia, è necessaria la conversione di tipo, e l'operazione da eseguire dipende dalla conversione effettuata. Le regole di conversione per +
danno priorità alla concatenazione di stringhe: se uno degli operandi è una stringa o un oggetto che si converte in una stringa, l'altro operando viene convertito in una stringa e viene eseguita la concatenazione. L'addizione viene eseguita solo se nessuno degli operandi è simile a una stringa.
Tecnicamente, l'operatore +
si comporta così:
- Se uno dei suoi valori operando è un oggetto, lo converte in un primitivo usando l'algoritmo da oggetto a primitivo descritto nella lezione apposita. Gli oggetti
Date
vengono convertiti dal loro metodotoString()
, e tutti gli altri oggetti vengono convertiti tramitevalueOf()
, se quel metodo restituisce un valore primitivo. Tuttavia, la maggior parte degli oggetti non ha un metodovalueOf()
utile, quindi vengono convertiti tramitetoString()
anch'essi. - Dopo la conversione da oggetto a primitivo, se uno degli operandi è una stringa, l'altro viene convertito in una stringa e viene eseguita la concatenazione.
- Altrimenti, entrambi gli operandi vengono convertiti in numeri (o in
NaN
) e viene eseguita l'addizione.
Ecco alcuni esempi:
1 + 2 // => 3: addizione
"1" + "2" // => "12": concatenazione
"1" + 2 // => "12": concatenazione dopo numero-a-stringa
1 + {} // => "1[object Object]": concatenazione dopo oggetto-a-stringa
true + true // => 2: addizione dopo booleano-a-numero
2 + null // => 2: addizione dopo null si converte in 0
2 + undefined // => NaN: addizione dopo undefined si converte in NaN
Infine, è importante notare che quando l'operatore +
viene usato con stringhe e numeri, potrebbe non essere associativo. Cioè, il risultato può dipendere dall'ordine in cui vengono eseguite le operazioni.
Per esempio:
1 + 2 + " topini ciechi" // => "3 topini ciechi"
1 + (2 + " topini ciechi") // => "12 topini ciechi"
La prima riga non ha parentesi, e l'operatore +
ha associatività da sinistra a destra, quindi i due numeri vengono addizionati prima, e la loro somma viene concatenata con la stringa. Nella seconda riga, le parentesi alterano questo ordine delle operazioni: il numero 2 viene concatenato con la stringa per produrre una nuova stringa. Poi il numero 1 viene concatenato con la nuova stringa per produrre il risultato finale.
Operatori Aritmetici Unari
Gli operatori unari modificano il valore di un singolo operando per produrre un nuovo valore. In JavaScript, gli operatori unari hanno tutti alta precedenza e sono tutti associativi a destra. Gli operatori aritmetici unari descritti in questa sezione (+
, -
, ++
, e --
) convertono tutti il loro singolo operando in un numero, se necessario. Nota che i caratteri di punteggiatura +
e -
sono usati sia come operatori unari che binari.
Gli operatori aritmetici unari sono i seguenti:
-
Più unario (
+
)L'operatore di addizione unario converte il suo operando in un numero (o in
NaN
) e restituisce quel valore convertito. Quando usato con un operando che è già un numero, non fa niente. Questo operatore non può essere usato con valori BigInt, poiché non possono essere convertiti in numeri regolari. -
Meno unario (
-
)Quando
-
è usato come operatore unario, converte il suo operando in un numero, se necessario, e poi cambia il segno del risultato. -
Incremento (
++
)L'operatore
++
incrementa (cioè, aggiunge 1 a) il suo singolo operando, che deve essere un lvalue (una variabile, un elemento di un array, o una proprietà di un oggetto). L'operatore converte il suo operando in un numero, aggiunge 1 a quel numero, e assegna il valore incrementato indietro nella variabile, elemento, o proprietà.Il valore di ritorno dell'operatore
++
dipende dalla sua posizione relativa all'operando. Quando usato prima dell'operando, dove è conosciuto come operatore di pre-incremento, incrementa l'operando e valuta al valore incrementato di quell'operando. Quando usato dopo l'operando, dove è conosciuto come operatore di post-incremento, incrementa il suo operando ma valuta al valore non incrementato di quell'operando. Consideriamo la differenza tra queste due righe di codice:let i = 1, j = ++i; // i e j sono entrambi 2 let n = 1, m = n++; // n è 2, m è 1
Nota che l'espressione
x++
non è sempre la stessa dix=x+1
. L'operatore++
non esegue mai concatenazione di stringhe: converte sempre il suo operando in un numero e lo incrementa. Sex
è la stringa "1",++x
è il numero 2, max+1
è la stringa "11".Nota anche che, a causa dell'inserimento automatico di punto e virgola di JavaScript, non possiamo inserire un'interruzione di riga tra l'operatore di post-incremento e l'operando che lo precede. Se lo facciamo, JavaScript tratterà l'operando come un'istruzione completa da sola e inserirà un punto e virgola prima di esso.
Questo operatore, sia nella sua forma di pre-incremento che di post-incremento, è più comunemente usato per incrementare un contatore che controlla un ciclo
for
. -
Decremento (
--
)L'operatore
--
si aspetta un operando lvalue. Converte il valore dell'operando in un numero, sottrae 1, e assegna il valore decrementato indietro all'operando. Come l'operatore++
, il valore di ritorno di--
dipende dalla sua posizione relativa all'operando. Quando usato prima dell'operando, decrementa e restituisce il valore decrementato. Quando usato dopo l'operando, decrementa l'operando ma restituisce il valore non decrementato. Quando usato dopo il suo operando, nessuna interruzione di riga è permessa tra l'operando e l'operatore.
Operatori Bitwise
Gli operatori bitwise eseguono manipolazioni a basso livello dei bit nella rappresentazione binaria dei numeri. Anche se non eseguono operazioni aritmetiche tradizionali, sono categorizzati qui come operatori aritmetici perché operano su operandi numerici e restituiscono un valore numerico. Quattro di questi operatori eseguono algebra booleana sui singoli bit degli operandi, comportandosi come se ogni bit in ogni operando fosse un valore booleano (1=vero, 0=falso). Gli altri tre operatori bitwise sono utilizzati per spostare i bit a sinistra e a destra. Questi operatori non sono comunemente utilizzati nella programmazione JavaScript, e se non si ha familiarità con la rappresentazione binaria degli interi, inclusa la rappresentazione in complemento a due degli interi negativi, probabilmente si può saltare questa sezione.
Gli operatori bitwise si aspettano operandi interi e si comportano come se questi valori fossero rappresentati come interi a 32 bit piuttosto che come valori a virgola mobile a 64 bit. Questi operatori convertono i loro operandi in numeri, se necessario, e poi forzano i valori numerici in interi a 32 bit eliminando qualsiasi parte frazionaria e qualsiasi bit oltre il 32°. Gli operatori di spostamento richiedono un operando sul lato destro tra 0 e 31. Dopo aver convertito questo operando in un intero non firmato a 32 bit, eliminano qualsiasi bit oltre il 5°, il che produce un numero nell'intervallo appropriato. Sorprendentemente, NaN
, Infinity
e -Infinity
si convertono tutti a 0 quando vengono utilizzati come operandi di questi operatori bitwise.
Tutti questi operatori bitwise eccetto >>>
possono essere utilizzati con operandi di numeri regolari o con operandi BigInt
.
-
AND Bitwise (
&
)L'operatore
&
esegue un'operazione AND booleana su ogni bit dei suoi argomenti interi. Un bit è impostato nel risultato solo se il bit corrispondente è impostato in entrambi gli operandi. Per esempio,0x1234 & 0x00FF
restituisce0x0034
. -
OR Bitwise (
|
)L'operatore
|
esegue un'operazione OR booleana su ogni bit dei suoi argomenti interi. Un bit è impostato nel risultato se il bit corrispondente è impostato in uno o entrambi gli operandi. Per esempio,0x1234 | 0x00FF
restituisce0x12FF
. -
XOR Bitwise (
^
)L'operatore
^
esegue un'operazione OR esclusivo booleana su ogni bit dei suoi argomenti interi. OR esclusivo significa che o l'operando uno ètrue
o l'operando due ètrue
, ma non entrambi. Un bit è impostato nel risultato di questa operazione se un bit corrispondente è impostato in uno (ma non entrambi) dei due operandi. Per esempio,0xFF00 ^ 0xF0F0
restituisce0x0FF0
. -
NOT Bitwise (
~
)L'operatore
~
è un operatore unario che appare prima del suo singolo operando intero. Opera invertendo tutti i bit nell'operando. A causa del modo in cui gli interi con segno sono rappresentati in JavaScript, applicare l'operatore~
a un valore è equivalente a cambiare il suo segno e sottrarre 1. Per esempio,~0x0F
restituisce0xFFFFFFF0
, o −16. -
Spostamento a sinistra (
<<
)L'operatore
<<
sposta tutti i bit nel suo primo operando a sinistra del numero di posizioni specificato nel secondo operando, che dovrebbe essere un intero tra 0 e 31. Per esempio, nell'operazionea << 1
, il primo bit (il bit delle unità) dia
diventa il secondo bit (il bit dei due), il secondo bit dia
diventa il terzo, ecc. Uno zero è utilizzato per il nuovo primo bit, e il valore del 32° bit è perso. Spostare un valore a sinistra di una posizione è equivalente a moltiplicare per 2, spostare due posizioni è equivalente a moltiplicare per 4, e così via. Per esempio,7 << 2
restituisce 28. -
Spostamento a destra con segno (
>>
)L'operatore
>>
sposta tutti i bit nel suo primo operando a destra del numero di posizioni specificato nel secondo operando (un intero tra 0 e 31). I bit che vengono spostati fuori a destra sono persi. I bit riempiti a sinistra dipendono dal bit di segno dell'operando originale, al fine di preservare il segno del risultato. Se il primo operando è positivo, il risultato ha zeri posti nei bit alti; se il primo operando è negativo, il risultato ha uni posti nei bit alti. Spostare un valore positivo a destra di una posizione è equivalente a dividere per 2 (scartando il resto), spostare a destra due posizioni è equivalente alla divisione intera per 4, e così via.7 >> 1
restituisce 3, per esempio, ma nota che−7 >> 1
restituisce −4. -
Spostamento a destra con riempimento di zeri (
>>>
)L'operatore
>>>
è proprio come l'operatore>>
, eccetto che i bit spostati a sinistra sono sempre zero, indipendentemente dal segno del primo operando. Questo è utile quando vogliamo trattare valori firmati a 32 bit come se fossero interi non firmati.−1 >> 4
restituisce −1, ma−1 >>> 4
restituisce0x0FFFFFFF
, per esempio. Questo è l'unico degli operatori bitwise JavaScript che non può essere utilizzato con valori BigInt. BigInt non rappresenta i numeri negativi impostando il bit alto nel modo in cui lo fanno gli interi a 32 bit, e questo operatore ha senso solo per quella particolare rappresentazione in complemento a due.