Menu

Sintassi e punto e virgola in JavaScript: le regole ASI

Come funziona la sintassi di JavaScript (istruzioni, blocchi, espressioni) e la verità sul punto e virgola, l'inserimento automatico (ASI) e quando può fregarti.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Il codice JavaScript è una sequenza di istruzioni

Un programma JavaScript è un elenco di istruzioni: comandi che il motore esegue dall'alto verso il basso. Dichiarare una variabile è un'istruzione. Chiamare una funzione è un'istruzione. Un blocco if o un for è un'istruzione. Le istruzioni sono separate tra loro da punti e virgola.

Tre istruzioni, tre punti e virgola. Il motore esegue la prima, poi la seconda, poi la terza. Facile.

Spazi e indentazione non significano nulla per il parser. Potresti mettere tutte e tre le istruzioni su una sola riga separate da punti e virgola e funzionerebbe allo stesso modo. Indentiamo per chi legge, non per il motore.

I blocchi raggruppano le istruzioni

Le parentesi graffe { } creano un blocco: un gruppo di istruzioni che il motore tratta come un'unità. Vedrai blocchi ovunque: corpi di funzione, rami di if, corpi dei cicli.

Le due chiamate a console.log dentro le graffe sono il corpo dell'if. Nota che non c'è un punto e virgola dopo la } di chiusura: i blocchi non sono istruzioni che vanno terminate. L'istruzione if nel suo insieme finisce quando finisce il blocco.

Questo spiazza chi viene da linguaggi in cui ogni } vuole un ; dopo. In JavaScript, né un blocco a sé né un blocco di controllo del flusso ne hanno bisogno.

Espressioni e istruzioni

Una distinzione che conviene chiarire presto: le espressioni producono un valore, le istruzioni fanno qualcosa.

  • 2 + 3 è un'espressione. Vale 5.
  • let x = 2 + 3; è un'istruzione. Dichiara una variabile e le assegna il risultato di un'espressione.
  • console.log("hi") è un'espressione (la chiamata di una funzione restituisce undefined), ma scritta su una riga a sé con un punto e virgola diventa un'istruzione di espressione.

Quasi sempre non devi pensarci. Diventa importante quando incontri le arrow function, gli operatori ternari e i punti in cui JavaScript vuole un'espressione ma tu gli hai dato un'istruzione (o viceversa).

La questione del punto e virgola

La risposta onesta è questa: JavaScript ha una funzionalità chiamata inserimento automatico del punto e virgola (ASI, dall'inglese Automatic Semicolon Insertion) che inserisce al posto tuo i punti e virgola mancanti nella maggior parte degli a capo. Per questo un codice come questo funziona senza problemi:

Niente punti e virgola, nessun errore. L'ASI guarda ogni a capo e si chiede: "il token successivo potrebbe continuare l'istruzione corrente?" Se no, inserisce un punto e virgola.

Grazie all'ASI, in giro esistono due stili legittimi:

  • Sempre il punto e virgola. La maggior parte dei progetti, dei tutorial e delle guide di stile.
  • Niente punto e virgola. Usato da alcuni progetti moderni (lo stile Standard, alcune codebase React). Si affida all'ASI più un paio di accorgimenti difensivi.

Funzionano entrambi. Nessuno dei due è "sbagliato". Quello che è sbagliato è l'incoerenza: mescolare gli stili nello stesso file rende i bug più difficili da individuare.

Dove l'ASI ti frega

L'ASI fa la cosa giusta circa il 99% delle volte. Il restante 1% sono le righe che iniziano con un token che potrebbe continuare la riga precedente. I colpevoli sono [, (, `, +, - e /.

Guarda questo:

Ti aspetteresti che x e y si scambino. Invece l'ASI non inserisce un punto e virgola prima di [x, y], perché 10[x, y] è sintatticamente valido (l'accesso a un indice del numero 10). Il parser legge la riga 2 e la riga 3 come un'unica grande espressione, e ottieni un errore a runtime o un output senza senso.

La soluzione è un punto e virgola alla fine della riga 2:

Oppure, se scrivi senza punti e virgola, un punto e virgola all'inizio della riga a rischio:

Quel ; iniziale è l'accorgimento difensivo che usano le codebase senza punti e virgola. Sembra strano finché non sai perché c'è.

La trappola del return

Un caso di ASI vale la pena di impararlo a memoria, perché produce bug silenziosi. Se vai a capo subito dopo return, l'ASI inserisce lì un punto e virgola e la funzione restituisce undefined:

Chi l'ha scritto voleva restituire un oggetto. L'ASI ha visto return alla fine di una riga e ha chiuso l'istruzione sul posto. L'oggetto letterale è diventato codice irraggiungibile.

La soluzione è iniziare il valore sulla stessa riga di return:

La stessa regola vale per throw, break, continue e yield: non andare a capo tra la parola chiave e il suo valore.

Una regola semplice che funziona

Se stai iniziando, la strada più semplice è questa:

  1. Scrivi il punto e virgola in modo esplicito alla fine di ogni istruzione.
  2. Non metterlo dopo la } che chiude un blocco di if, for, while, dichiarazioni di funzione o corpi di classe.
  3. Mettilo invece dopo la } di un oggetto letterale o di un'espressione di funzione assegnata a una variabile: const f = function() {};.
  4. Usa un formatter (Prettier, o ESLint con una regola di stile) e smetti di pensarci. Il formatter applica quello che ha deciso il tuo team.

Questa regola non è una legge universale: è la convenzione che vedrai nella maggior parte del codice JavaScript che leggerai. Seguila finché non hai un buon motivo per fare diversamente.

Maiuscole, minuscole e identificatori

Due piccole regole che stanno bene qui:

  • JavaScript distingue tra maiuscole e minuscole. userName, username e UserName sono tre identificatori diversi.
  • Gli identificatori possono contenere lettere, cifre, _ e $, ma non possono iniziare con una cifra. Non possono nemmeno essere parole riservate come class, return o function.

Il $ è valido, ma per convenzione di solito è riservato a cose specifiche di una libreria (jQuery lo usava in passato, alcuni sistemi di template lo fanno ancora). Raramente lo sceglierai tu.

Prossimo passo: la modalità strict

Il JavaScript moderno gira in silenzio in una variante più rigorosa del linguaggio chiamata modalità strict, che trasforma alcuni comportamenti approssimativi in veri errori. I moduli ES e i corpi delle classi sono strict per impostazione predefinita, ma vale la pena sapere cosa cambia davvero: è l'argomento della prossima pagina.

Domande frequenti

Serve il punto e virgola in JavaScript?

Tecnicamente no: JavaScript ha l'inserimento automatico del punto e virgola (ASI, dall'inglese Automatic Semicolon Insertion), che lo aggiunge al posto tuo nella maggior parte degli a capo. In pratica, però, la maggior parte dei team lo scrive comunque in modo esplicito, perché l'ASI ha qualche caso limite (righe che iniziano con [, (, `, +, -, /) in cui sbaglia. Scegli uno stile e lascia che un formatter come Prettier lo applichi.

Cos'è l'inserimento automatico del punto e virgola in JavaScript?

L'ASI è la regola che permette a JavaScript di inserire i punti e virgola mancanti alla fine di una riga quando il token successivo non potrebbe continuare l'istruzione corrente. È il motivo per cui let x = 1 funziona senza punto e virgola. Fallisce quando una riga inizia proprio con qualcosa che può continuare la riga precedente, come [ o (, e JavaScript incolla in silenzio le due righe.

Qual è la sintassi di base di un'istruzione JavaScript?

Un'istruzione è un comando: la dichiarazione di una variabile, la chiamata di una funzione, un blocco if, un ciclo. Le istruzioni sono separate da punti e virgola (espliciti o inseriti). I blocchi di istruzioni vanno dentro { }. Spazi e indentazione vengono ignorati dal parser, quindi la formattazione serve alle persone, non al motore.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA