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. Vale5.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 restituisceundefined), 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:
- Scrivi il punto e virgola in modo esplicito alla fine di ogni istruzione.
- Non metterlo dopo la
}che chiude un blocco diif,for,while, dichiarazioni di funzione o corpi di classe. - Mettilo invece dopo la
}di un oggetto letterale o di un'espressione di funzione assegnata a una variabile:const f = function() {};. - 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,usernameeUserNamesono tre identificatori diversi. - Gli identificatori possono contenere lettere, cifre,
_e$, ma non possono iniziare con una cifra. Non possono nemmeno essere parole riservate comeclass,returnofunction.
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.