Sommario
< Home
Stampa

­­­Introduzione a Javascript

Storia di Javascript

Javascript è un linguaggio che nasce alla fine degli anni ’90, come semplice estensione del browser per introdurre animazioni nelle pagine web. A seguito della sua standardizzazione è diventato il linguaggio standard per gestire le animazioni e l’interazione con l’utente nelle pagine web. Nel corso dei primi anni 2000, col vero e proprio boom di Internet, Javascript è diventato il principale linguaggio per la realizzazione di applicazioni per il web nel browers, con nuove funzionalità ed in particolare la capacità di eseguire richieste HTTP al server senza ricaricare la pagina (la cosiddetta tecnologiaAJAX”). Dopo il 2010, con l’avvento delle tecnologie mobili e di ulteriori funzionalità, il linguaggio è diventato il principale riferimento per lo sviluppo di vere e proprie applicazioni web-based residenti sui dispositivi client (pc, tablet, smartphone, smartTV, ecc.). Dal 2015 in avanti, con la diffusione dell’ambiente Node, Javascript è entrato anche nel mondo desktop, permettendo di realizzare applicazioni per pc, per server e applicazioni mobili.

Oggi Javascript è il linguaggio di programmazione più diffuso al mondo, in quanto è probabilmente l’unico linguaggio di programmazione (insieme al C++) con cui è possibile scrivere applicazioni per pc, server, web, mobile, smartTV, intelligenza artificiale, IoT e videgiochi. La community di sviluppatori Javascript è la più estesa al mondo (con ben 14 milioni di progetti sulla popolare piattaforma Github) e per Javascript sono stati realizzate migliaia di librerie e soprattutto framework di sviluppo, prima con JQuery e poi con React, Angular, Vue e Svelte, che oggi sono utilizzati nella praticamente totalità dei siti web (nella parte eseguita lato client).

Buona parte del successo odierno di Javascript lo si deve comunque non solo alla community ma ai grandi investimenti che vi hanno dedicato società come Google (autrice del motore di esecuzione più diffuso e di Angular), Meta (con React), Apple (con la diffusione di iOs) e infine di Microsoft (che ha realizzato il linguaggio Typescript, una estensione fortemente tipizzata di Javascript).

Le caratteristiche del linguaggio sono gestite da ECMA, una associazione internazionale che si occupa di standard industriali e di cui fanno parte tutte le aziende sopra citate. Lo standard di linguaggio di Javascript è chiamato ECMAScript (ES). Le due principali versioni che hanno reso Javascript un linguaggio in grado di realizzare vere e proprie applicazioni per il web sono ES5 (2009, programmazione ad oggetti e funzionale) ed ES6 (2015, classi, moduli, lambda functions).

Caratteristiche principali

Javascript è un linguaggio di programmazione interpretato. Un linguaggio interpretato è un linguaggio che non viene tradotto in codice macchina in fase di rilascio, ma viene eseguito da un programma specifico, detto runtime, che interpreta ed esegue le istruzioni in un contesto di esecuzione appositamente predisposto, che simula una macchina di Von Neumann, quindi con uno stack ed uno heap.

Il runtime più utilizzato di Javascript è Google V8[1], che garantisce oggi prestazioni simili a quelle di un linguaggio compilato. Questo perchè il linguaggio alla prima esecuzione viene compilato con una tecnica di compilazione JIT[2].

Javascript può girare su browser, su deskop (ad esempio il popolare editor Visual Studio Code), su app mobile (come libreria interna WebView sia su Android che iOs), su tutte le principali SmartTV (Android, Tizen, WebOS, TvOS, ecc.).

Javascript è un linguaggio che supporta tutti e 3 i principali paradigmi di programmazione: strutturato, ad oggetti e funzionale.

Il paradigma strutturato consiste in quel modello di programmazione dove si usano costrutti di programmazione condizionali ed iterazioni sui dati, anche tramite una strutturazione basata su sottoprogrammi/funzioni, mantenendo separati i dati dal codice, analogamente a quanto avviene nel linguaggio C.

Nel paradigma ad oggetti, i dati e le funzioni sono inglobati in contenitori chiamati oggetti, in cui i dati sono collegati alle funzioni che li manipolano. In Javascript è possibile manipolare oggetti sia tramite l’utilizzo di classi (analogamente a Java/C#/C++) sia creandoli direttamente. L’argomento sarà poi approfondito specificatamente.

Nel paradigma funzionale, le funzioni sono a tutti gli effetti oggetti quindi possono essere memorizzate in variabili, ed inoltre possono restituire altre funzioni. Anche questo argomento sarà approfondito in modo specifico.

Javascript ha un modello di programmazione monothread e per garantire reattività nell’interfaccia utente si basa su un modello di esecuzione asincrono e basato su eventi.

Per asincrono si intende che il runtime esegue una istruzione alla volta e per le attività bloccanti (ad esempio una richiesta di una risorsa su internet) esegue delle chiamate di libreria che svolgono queste attività in background (fuori dal runtime di Javascript). Inoltre Javascript è basato su una programmazione basata su eventi: è possibile quindi registrare delle funzioni, dette “callback”, che si attivano se avvengono degli eventi (ad esempio il click di un utente su un pulsante nel browser).

La sintassi di base di JS è ereditata, come altri linguaggi, dal C e dal Java (da cui il nome Javascript). Per una trattazione specifica sui costrutti del C si rimanda alla sezione specifica.

In questa dispensa vedremo il funzionamento base del linguaggio, la gestione delle variabili e i principali costrutti.

Console

Siccome Javascript non funziona (a differenza del C) con un input/output su schermo, a supporto del programmatore è previsto l’oggetto console : è un oggetto che permette di mostrare informazioni in una apposita schermata di console presente nel browser: è possibile accedere alla schermata di console cliccando col tasto destro sulla pagina html e accedendo al menu per l’accesso agli strumenti di sviluppo. 

Il metodo (principale) usato è console.log[3] ed ha per argomento qualsiasi espressione. Se l’espressione è “stampabile” viene mostrato il risultato, altrimenti (ad esempio per oggetti complessi) viene mostrato un segnaposto al posto del risultato.

Veniamo ora al linguaggio.

Variabili e costanti

Javascript è un linguaggio fortemente tipizzato. Questo significa che ogni variabile ha un tipo associato che ne identifica la valorizzazione e le operazioni possibili. 

Il tipo di dato è dedotto (“inferito”) dinamicamente ogni volta che si assegna una variabile, quindi la tipizzazione in JS è definita a runtime. Il “nome” di una variabile è un “alias” cioè un riferimento al dato presente in memoria. Questo alias può essere associato quindi a qualsiasi oggetto o altro contenuto. Non va comunque fatta confusione coi puntatori, come vedremo. Per la cancellazione delle aree di memoria non più associate a delle variabili è previsto dal runtime uno speciale strumento, chiamato garbage collector, che libera la memoria dereferenziata.

I tipi base sono tre: stringnumberbool. Sono poi previsti tipi oggetto, come array, dizionari, oggetti, funzioni, classi. Le variabili vanno dichiarate con let, le costanti con const. Un simbolo assegnato come costante non può cambiare valore.[4]

let x = 3;

const myString = “Ciao”;

Come anticipato sopra è possibile cambiare il tipo di una variabile:

let a=3; // adesso è un number

a=”ciao”; // ora è una stringa

—————————————————————————–

Le variabili/costanti si inizializzano senza indicare il tipo, che viene inferito dall’interprete. 

Sono poi previste espressioni speciali:

– undefined: riferito ad una variabile indica che non è stata dichiarata, o è stata dichiarata ma mai assegnata;

– null: riferito ad una variabile a cui è stato assegnato il valore nullo, un codice speciale che indica che la variabile è comunque valorizzata.

Undefined e null non sono la stessa cosa, in quanto null è un valore assegnabile, mentre undefined è uno stato generico che indica una mancata assegnazione. Undefined sono tutte le variabili che non sono mai state assegnate, null invece indica che una assegnazione c’è stata.

Sintassi

La sintassi di Javascript prevede le seguenti regole:

– ogni istruzione deve terminare con un ; 

let i = 0;

– si possono usare i blocchi per raggruppare più istruzioni:

{

     let i=0;

     let j = i+2;

}

Espressioni

Una espressione è una struttura composta da elementi contenenti valori oppure operatori. Essa può essere oggetto di assegnazione (se a destra dell’uguale), può essere parametro di funzione oppure essere valutata all’interno di una condizione. L’espressione viene sempre valutata prima del suo utilizzo.

Espressioni principali di Javascript:

– literal: valori numerici o stringhe assoluti scritti dal programmatore. es 1, False, “Ciao”.

– espressioni aritmetiche. Es. “5+4”, “90/2”. Possono essere applicati operatori matematici (+,-,/,*,%, ecc.).

– espressioni stringa: Es. “ciao” + ” Mario”. Possono essere applicati operatori come + (concatenazione).

– espressioni booleane. Es. 5 > 3. Possono essere solo True o False. Possono essere applicati operatori booleani (<, <=, >, >=, !=, ==, !== e !==). 

– operatori unari. Es. typeof 5 (-> number), c++ (incrementa di 1 il valore di c)

– null e undefined.

– variabili e costanti.

– NaN (vedi sotto)

In Javascript la conversione di tipo è automatica ogni volta ciò sia possibile. 

Ad esempio l’espressione 5+”” produce una stringa “5”. Tuttavia non sempre è possibile farlo, ad in tal caso Javascript stampa l’espressione “NaN” (Not a Number). Es: 5*”” restituisce NaN.

Operatori booleani 

==
!=
>=
<=
Uguaglianza debole. Questo operatore permette di confrontare oggetti di tipo diverso. Il sistema implicitamente effettua la conversione. Es:1 == “1” -> Trueundefined == null -> True
===
!==
>==<==
Uguaglianza forte.Questo operatore permette di confrontare oggetti dove viene prima confrontato il tipo e poi il valore.1 === “1” -> Falseundefined === null -> False
truthySi indica come truthy qualsiasi espressione diversa da 0, “”, false, null, undefined. Le espressioni truthy se valutate in un if, while, ecc sono considerate true.
falsySi indica come falsy qualsiasi espressione uguale da 0, “”, false, null, undefined. Le espressioni falsy se valutate in un if, while, ecc sono considerate false.

Nella prassi bisogna sempre usare l’operatore di uguaglianza forte, l’uso dell’uguaglianza debole sebbene sia possibile, è considerato deprecato.

Matematica e conversioni

E’ possibile convertire da stringa a numero con i seguenti operatori.

parseInt(“12”) // 12
parseInt(“12abc”)      // 12
parseInt(“a12bc”)      // NaN
parseInt(“12.5”)       // 12
parseInt(“12”, 8)
parseFloat(“12”)               //12
parseFloat(“12.5”)

L’oggetto Math mette a disposizione un po’ di funzioni matematiche utili. 

Math.random(), Math.floor(), Math.ceil(), Math.round(), Math.abs(), Math.sin(), Math.cos(), Math.PI, Math.E, Math.sqrt(), Math.pow(), Math.min(), Math.max()

Stringhe

Andiamo a vedere un elenco di azioni che si possono svolgere con le stringhe.

FunzionalitàCosa fa
nomeStringa.split(delimitatore)Il metodo split permette di suddividere una stringa in un array di stringhe, divise da un separatore.  
array.join(delimitatore)Unisce gli elementi di un array in una stringa.
nomeStringa.replace(a,b)Sostituisce la prima occorrenza di a con b. Il risultato è la nuova stringa.
nomestringa.substring(a,b)Estrae la sottostringa con indice da a (compreso) a b (escluso).
nomestringa.charAt(x);estrae il carattere alla posizione x
nomestringa.charCodeAt(x);estrae il codice carattere alla posizione x

Esempi:

FunzionalitàEsempio
nomeStringa.split(delimitatore)let string = “1,2,3,4,5”;let numbers = string.split(“,”);
array.join(delimitatore)let list = [1,2,3,4,5];const result = list.join(“-“);
nomeStringa.replace(a,b)const string = “Ciao Mario”;string = string.replace(“Ciao”, “Hello”);
nomestringa.substring(a,b)const string = “Ciao Mario”;sub = string.substring(0,4);
nomestringa.charAt(x);const c = string.charAt(3);
nomestringa.charCodeAt(x);const code = string.charCodeAt(3);

Le stringhe in Javascript si possono fare anche multilinea.

const string = `Ciao sono 
una stringa
multilinea
`;

ed è possibile inserire dei valori:

const nome = "Mario";
const cognome = "Rossi";
const string = `Ciao sono ${_nome} ${_cognome}`;

Data-ora

Qui di seguito le operazioni fondamentali sulle stringhe.

FunzionalitàCosa fa
new Date();Restituisce un oggetto che contiene la data ora corrente.  
new Date(string);Restituisce un oggetto che contiene la data indicata dalla stringa (opportunamente formattata);
new Date(y,M,d,h,m,s,ms);Restituisce un oggetto dato anno, mese, giorno, ora, minuti secondi, millsecondi
getDate(), getMonth(), getFullYear(), getHours(), getMinutes(), getSeconds()Restituisce gli elementi di una data.
Date.now()Restituisce il timestamp corrente (in millisecondi).
getTime();Restituisce il timestamp della data d (che deve essere un oggetto Date)

Costrutti programmazione strutturata

Nota: le parentesi quadre indicano codice opzionale.

CostruttoSpiegazione ed esempio:
if (condizione)   istruzione [else   istruzione]if (x==3) {  console.log(“x è uguale a 3”);} else { console.log(“x non è uguale a 3”);};
for (inizializzazionecondizioneiterazione)          istruzionefor (int i=0; i<10; i++) {  console.log(“x: ” + x);}
while (condizione)   istruzionei=0;while (i<10) {  console.log(“x: ” + x);};
do   istruzione while (condizione)i=0;do {  console.log(“x: ” + x);} while (i<10);
switch (espressione): {  case valore: istruzione; break;  [case valore: istruzione; break; …]  [case default: istruzione]}switch (x): { case 1: {console.log(“1”); break; } case 3: {console.log(“3”); break; } case default: {console.log(“default”);}
valore = condizione ? expr1 : expr2;Il codice equivale a: if (expr1) {    valore = expr1;} else {    valore = expr2;} int a = b > c ? b : c
valore = expr1 || expr2;if (expr1) {   valore = expr1;} else {   valore = expr2;} int a = b || c;

Funzioni

Le funzioni possono essere definite in due modi, ciascuno con due varianti:

Funzione standard – variante classica:

function somma(x, y) {
  return x+y;
} 

Funzione standard – variante anonima

let f = function(x, y) {
  return x+y;
}

Funzione freccia (detta anche lambda)

const f = (x,y) => {
  return x+y;
}

Funzione freccia compatta, notare che vengono eliminate parentesi e istruzione return, questa notazione si può usare per funzioni di una riga di codice che ritornano un valore.

const f = x,y => x+y

Le tipologie di funzione sono praticamente identiche[5]. Le funzioni sono oggetti in memoria e vanno trattati come tali: è possibile come visto salvare una funzione in una variabile, in array e dizionari, si possono restituire nelle funzioni, ed altro ancora. Le funzioni sono molto articolate e sono una caratteristica fondamentale di Javascript. Sarà previsto un approfondimento specifico.

Oggetti

In Javascript tutte le variabili (e costanti) sono oggetti (eccetto number e bool).

Quindi array, dizionari e funzioni sono oggetti, così come qualsiasi oggetto del browser (se JS è eseguito nel browser), importato, generato da funzione o classe. 

In Javascript inoltre gli oggetti sono sempre dinamici. E’ quindi sempre possibile aggiungere proprietà e metodi a oggetti esistenti, qualunque sia la loro forma originaria. Anche array, dizionari e funzioni sono oggetti e quindi godono delle stesse identiche caratteristiche, anche la dinamicità.


[1] V8 è scritto in C++ e può essere integrato come libreria in applicazioni C++.

[2] la compilazione JIT (“Just in time”) consiste in una precompilazione del codice subito prima dell’esecuzione. La prima esecuzione è leggermente più lenta le successive sono velocissime.

[3] ma sono previsti metodi per ogni tipo di informazione: debug, error, info, warning.

[4] Nelle versioni fino al 2015 di Javascript la dichiarazione di una variabile era indicata con var. Per questo, erroneamente ancora oggi, in molti siti e libri si usano ancora esempi con var, oggi deprecati.

[5] le funzioni freccia hanno, in alcuni rari casi, delle limitazioni ma vanno oltre la trattazione del presente corso.