Pillole di Javascript: il punto e virgola

− Che, scusate se sono poche, ma settecentomila lire, punto e virgola, noi, noi ci fanno specie che questanno, una parola, questanno c’è stato una grande moria delle vacche…
− Una grande…
− Come voi ben sapete. Punto!
− Punto.
− Due punti! Ma sì, fai vedere che abbondiamo, abbondandis adbondandum.

Totò e Peppino De Filippo, in Totò, Peppino e… la malafemmina, 1956

Uno degli automatismi più evidenti in Javascript è il punto e virgola opzionale. La sintassi del linguaggio non obbliga ad inserire il punto e virgola alla fine dell’istruzione, come invece accade per molti altri linguaggi. Ad esempio le istruzioni:

console.log("hello");
console.log("hello")

sono entrambe valide. Il linguaggio permette anche di dividere una istruzione su più righe. Ad esempio le due righe seguenti formano un’unica istruzione, che assegna alla variabile c il valore 42;

var c = 
40 + 2

Le cose iniziano a farsi interessanti con questo esempio:

var a = 40
var b = 2
var c = a + b
(40 + 2)

Intuitivamente ci si aspetterebbe che alla variabile c sia assegnato il valore 42, e che l’ultima istruzione (40 + 2) venga valutata e il suo risultato semplicemente scartato, dato che non viene assegnato a nulla. Invece l’esecuzione del codice dà il seguente errore:

TypeError: b is not a function

Questo succede perché l’interprete vede le ultime due righe come un’unica istruzione, e quindi le interpreta come “var c = a + b(40 + 2)”, che da errore dato che b non è una funzione. Naturalmente inserendo a mano il punto e virgola alla fine di ogni riga il codice sarebbe stato interpretato così come ci si aspetterebbe.

L’algoritmo con il quale l’interprete decide dove terminare l’istruzione è chiamato Automatic Semicolon Intertion (ASI). L’interprete divide le righe nelle sue parti più piccole (token). Quando incontra un carattere di fine linea controlla se il primo token della riga successiva può essere posizionato di seguito alla riga attuale senza generare un errore di sintassi. In caso affermativo, la riga successiva è considerata il proseguimento dell’attuale, altrimenti viene inserito un punto e virgola “virtuale” alla fine della riga.

Il mio consiglio è di inserire sempre a mano il punto e virgola, per evitare di cadere in situazioni come quella descritta sopra. Va considerato anche che la sintassi del linguaggio cambia con il tempo, per cui due righe che oggi sono considerate separate, perché il primo token della seconda riga non può stare sintatticamente in fondo alla prima riga, un domani potrebbero invece essere considerate una sola istruzione, cambiando quindi il comportamento del programma con un semplice aggiornamento dell’interprete.

Occorre fare attenzione anche ad un’altro dettaglio. Alcuni token, come il “return”, non possono essere seguiti da un accapo, per cui non è possibile dividere l’istruzione su più righe. Per esempio il codice:

return
a+b;

intuitivamente dovrebbe eseguire il return dell’espressione (a + b), in realtà viene interpretato come:

return;
a + b;

che esegue il return di “undefined”, e ignora l’istruzione successiva. I token soggetti a questa restrizione sono i seguenti: continue, break, return, yield, yield*, module.

Infine una regola speciale è applicata per gli operatori di incremento “++” e decremento “–“. Questi operatori possono essere usati come prefix oppure come postfix. In caso di ambiguità:

a
++
b

L’operatore viene considerato di prefix (a; ++b;).

Precedente Variabili in Eclipse Successivo Pillole di Javascript: tipi di dato