JavaScript, HTML, CSS e... !
0 commenti

MEME JavaScript #003 --> 0 == '0', 0 == [] e '0' == []

Spieghiamo il MEME JavaScript: Coercizione

Questo MEME gioca sull'operatore di uguaglianza e il suo comportamento in termini di risultato quando viene utilizzato in JavaScript per il confronto tra 2 valori.

La sintassi dell’operatore di uguaglianza è ==, altrimenti con un singolo = si tratterebbe di assegnazione, come appunto assegnare un valore ad una variabile. Puoi trovare maggiori informazioni su questo operatore nella video lezione dedicata nel mio corso sul JavaScript Semplificato per Google: https://www.youtube.com/watch?v=9agqHjskIW8

L'operatore di uguaglianza restituisce true se i valori dei suoi operandi sono uguali, altrimenti false.

1 == 1 // true

1 == 2 // false

Ma vediamo subito nella pratica l'effetto mostrato nell'immagine, utilizzerò direttamente la console del browser. Quindi... se è vero che 0 inteso come numero viene rilevato uguale a 0 inteso come stringa (0 == "0") e se è vero che 0 inteso come numero viene rilevato uguale ad array vuoto (0 = []), per la proprietà transitiva ci si potrebbe aspettare che 0 inteso come stringa venga rilevato uguale ad array vuoto, e invece in questo caso il confronto, proprio come nel MEME, dà come risultato falso

0 == "0" // true

0 == [] // true

"0" == [] // false

Dal momento che può sembrare strano già il risultato del primo confronto, appunto che un numero venga considerato uguale ad una stringa, al fine di spiegare questo MEME farò riferimento alle specifiche di ECMAScript, uno standard di linguaggio di scripting pensato per garantire l'interoperabilità delle pagine web tra diversi browser.

Una particolarità, è che se facessi lo stesso confronto in Java, anziché in JavaScript, otterrei un errore (error: incomparable types: int and String) poiché un numero intero e una stringa in quel linguaggio non sono comparabili ed è necessario pertanto effettuare un'operazione preliminare di conversione nello stesso tipo.

public class ConfrontoTraValori{
     public static void main(String []args){
        int valore1 = 0;
        String valore2 = "0";
        if (valore1 == valore2) {
            System.out.println("Valori confrontati");
        }
     }
}

// error: incomparable types: int and String

E allora perché in JavaScript restituisce true? Perché questo linguaggio effettua un'operazione chiamata coercizione, ovvero modifica automaticamente un valore da un tipo ad un altro. Ed è proprio questa operazione, che viene fatta in modo trasparente, ad essere la chiave di lettura del MEME.

Infatti, nella specifica di ECMAScript (punto 4) possiamo leggere che in caso di confronto tra 2 valori,

Se x è un Numero e y è una Stringa, viene restituito x == ToNumber(y)

Quindi eseguire 0 == "0" (con il secondo valore di tipo stringa) è la stessa operazione di 0 == 0 (con il secondo valore di tipo numerico), alla fine sto a tutti gli effetti confrontando sempre 2 tipi numerici dal momento che se il primo valore è un numero e il secondo è una stringa, quest'ultimo subisce, volente o nolente, una conversione automatica.

Ma non sono solo le primitive, come stringhe e numeri, a seguire questo principio, ed è questo il motivo per il quale anche il secondo confronto, 0 == [], restituisce true. 

Nello specifico, consultando sempre la documentazione di ECMAScript, JavaScript forza l'oggetto con ToPrimitive() per trasformarlo in una stringa. Convertendo un array in stringa si ottiene il suo contenuto in formato stringa:

[1, 2, 3, 4, 5].toString() // "1, 2, 3, 4, 5"

Essendo l'array vuoto, la conversione porta di conseguenza ad una stringa vuota. Infatti 0 =="" (stringa vuota) risulta ancora come true.

A questo punto torniamo alla situazione vista in precedenza perché qua c'è un'altra sorpresa. Abbiamo visto che se il primo valore è un numero e il secondo è una stringa, la coercizione porta ad applicare ToNumber() al secondo valore. Ebbene, ToNumber("") di una stringa vuota restituisce 0.

Number("") // 0

Pertanto l'operazione diventa 0 == 0, ed ecco il perché l'operazione 0 == [] (array vuoto) risulta true.

Sulla base di queste regole va da sé che "0" == [] è false. Vediamo il perché!

Il confronto in questione porta ad applicare la coercizione del secondo valore ad una primitiva (come appena visto). Il risultato diventa quindi "0" == "" (0 inteso come stringa == a stringa vuota). Essendo entrambe stringhe il confronto non ha bisogno di ulteriori conversioni automatiche, infatti non avviene nessun'altra operazione implicita e poiché la prima stringa è evidentemente diversa dalla seconda, il risultato del confronto è false.

 

Ad ogni modo, è possibile avere un risultato più atteso e intuitivo utilizzando il triplo uguale (===).

Nel caso del doppio uguale == viene effettuata un'uguaglianza astratta (abstract equality) mentre nel caso del triplo uguale === viene effettuata un'uguaglianza stretta (strict equality).

Nel primo caso abbiamo visto che avviene una conversione implicita tra i valori da confrontare, nel secondo caso invece viene confrontato oltre al valore anche il tipo di dato, pertanto 0 === "0" non restituirà più true poiché nonostante i valori abbiamo visto che con il doppio = risultano interpretati come uguali, non avverrà alcuna coercizione, di conseguenza i tipi di valori confrontati sono diversi, il primo è un numero ed il secondo una stringa. Il risultato di conseguenza è false.

0 == "0" // true

0 === "0" // false

Grazie a questo MEME abbiamo avuto l'occasione di approfondire diverse curiosità del JavaScript. Abbiamo visto l'utilizzo dell'operatore di uguaglianza, l'applicazione automatica della coercizione in caso di confronto tra valori, una risorsa interessante (ECMAScript) da consultare per chiarire i misteri del linguaggio e l'uso del triplo uguale per un confronto stretto che considera sia il valore che il tipo di dato confrontato.

Spero che questo video ti sia piaciuto, fammelo sapere nei commenti e non peritarti a scrivere se hai altre curiosità del JavaScript che vorresti approfondire. Ti invito anche Iscriverti al mio Canale YouTube se ancora non l'hai fatto e ci vediamo al prossimo MEME. Ciao ;)

Tags

Michele Pisani

Michele Pisani

Sviluppatore Javascript ed esperto in Digital Analytics

L'esperienza nel settore Digital Analytics unita ad anni di sviluppo in Javascript ha trovato la massima espressione in Google Apps Script che mi ha permesso, con estrema facilità e poche righe di codice, di realizzare potenti applicazioni interattive e processi automatizzati integrati con i prodotti della G Suite.

Come contattarmi
scrivi un commento

0 Commenti

Non ci sono commenti

Nessuno ha ancora commentato questo articolo, fallo tu per primo!

scrivi un commento

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato.I campi contrassegnati da un * sono obbligatori
Puoi utilizzare i seguenti tag nei commenti:
[bold]testo[/bold] se vuoi evidenziare un testo con il grassetto[code]function helloworld() { }[/code] se vuoi pubblicare una porzione di codice[url]https://www.appsscript.it[/url] se devi riferirti ad un indirizzo web