ES6: l’avvento delle classi in Javascript (o quasi).

L’ultima incarnazione di Javascript (ES6*) ha portato diverse novità, tra cui l’introduzione delle Classi nella creazione degli oggetti, soppiantando la sintassi che definiva la “funzione costruttrice” che eravamo abituati ad usare. Ma come funzionano esattamente le “classi” in Javascript?

Diciamo subito le cose come stanno: più che di Classi sarebbe giusto chiamarle “Pseudo Classi” perché, ad essere sinceri, l’introduzione della keyword Class in Javascript è più un’operazione cosmetica che di sostanza; come vedremo, non si tratta infatti di Classi in senso stretto, come quelle che incontriamo in altri linguaggi di programmazione object-oriented (es. JAVA), Javascript rimane di fatto basato sui Prototipi (prototype-based), non sulle Classi (class-based), ma tant’è. Vediamo bene di cosa si tratta.

Prima di ES6*, volendo creare un oggetto, avremmo scritto una “Funzione Costruttrice” ed assegnato proprietà e metodi. Le prime, sotto forma di semplici coppie di variabili e valori; i secondi, definendo all’interno della Funzione Costruttrice altre funzioni, come fossero anch’esse proprietà abbinate a semplici variabili; oppure – meglio – ricorrendo al “Prototipo” dell’oggetto stesso. Meglio perché, così facendo, avremmo alleggerito la struttura di ogni singola istanza dell’oggetto, dal fardello di “portarsi dietro” i metodi che hanno in comune, delegando invece al Prototipo dell’oggetto tale compito, fungendo da riferimento univoco per tutte le istanze create su tale modello (attraverso il sistema di eredità prototipica).

// Prima di ES6 // utilizzando la Constructor Function

function Particle(x_, y_, w_, h_){
  this.x = x_;
  this.y = y_;
  this.w = w_;
  this.h = h_;
  /* // definendo il metodo all'interno dell'oggetto, come proprietà
  this.show = function(){
   rect(this.x, this.y, this.h, this.w);
  }
  */
}

/* Delegando al prototipo del mio oggetto la gestione della funzione Show una volta per tutte */

Particle.prototype.show = function(){
 rect(this.x, this.y, this.h, this.w);
 }

var p = new Particle(50, 50, 100, 50);
Se adesso, nella Console del mio Browser, digitassi “p“, potrei vedere la struttura del mio oggetto (provate per credere).

 

p
> Particle {x: 50, y: 50, w: 100, h: 50}
   h : 50
   w : 100
   x : 50
   y : 50
 > __proto__ :
     show : f()
     constructor : f Particle(x_, y_, w_, h_)
     __proto__ : Object
Con ES6 le cose sono leggermente cambiate, soprattutto a livello di sintassi: la funzione “speciale” deputata alla costruzione degli oggetti è stata mandata in pensione, in favore dell’introduzione della parola chiave “class“, ad indicare un blocco di codice che servirà da template per la creazione di un determinato tipo di oggetti,  seguita dal nome da noi scelto- con iniziale maiuscola -. All’interno di tale blocco è prevista la funzione “constructor“, deputata all’inizializzazione delle proprietà dell’oggetto, a seguire, i metodi che, dietro le quinte verranno automaticamente attribuiti al prototipo del nostro oggetto. Aggiorniamo l’esempio visto in precedenza con la nuova sintassi or ora descritta:

 

/* Costruiamo un oggetto "particella" utilizzando la sintassi introdotta da ES6 */

class Particle {
 constructor (x_, y_, w_, h_) { 
  this.x = x_;
  this.y = y_;
  this.w = w_;
  this.h = h_;
 }
 show() { 
  rect(this.x, this.y, this.h, this.w);
 }
 move() { 
  this.x = this.x + 1;
  this.y = this.y + 1;
 }
}

let p = new Particle(50, 50, 100, 50);
Ecco fatto, abbiamo appena creato un oggetto attraverso la nuova sintassi, incluso l’utilizzo della nuova keyword “let” che in ES6 ha sostituito la cara, vecchia, amata “var” (ma questa è un’altra storia). Tutto qua? Possiamo mettere a dormire il computer ed andarci a prendere una boccata d’aria? Nì. In verità, per completezza, ci sono alcune cose da aggiungere; quindi, se volete, fate pure una pausa, ma poi vi suggerisco di finire di leggere questo post.

 

Questa foto non ha assolutamente niente a che vedere con l’argomento di questo post. Interpretatela come una pausa pubblicitaria.

 

I fan di altri linguaggi di programmazione class-based, come Java e C++, potrebbero a questo punto esultare ma, come accennavo all’inizio di questo post, non è tutto oro quello che luccica. Ad esempio potremmo notare come Class Keyword in Javascript non supporta Membri Privati; è infatti sempre possibile accedere dall’esterno ai metodi definiti all’interno di una determinata classe e modificarli a piacimento (o piuttosto per errore). La ragione per cui tale supporto non è stato previsto nella recente release di ECMAScript è molto semplice: in realtà ES6 non ha introdotto delle vere e proprie Classi ma piuttosto una finzione sintattica, come possiamo facilmente dimostrare semplicemente interrogando la Console del Browser in merito al codice appena scritto:

 

typeof Particle 
"function"
Ebbene sì, se volete potete pure chiamarla Classe ma, quella da noi definita rimane, sotto al cofano di JavaScript pur sempre una funzione.

 

Particle.prototype.show 
ƒ (){
 rect(this.x, this.y, this.h, this.w);
 }
La sostanza non è cambiata rispetto a prima: rimane la struttura fondante basata sui Prototipi ed il principio di ereditarietà ad essi applicata.
Allora perché tutto questo sbattimento direte voi? Principalmente proprio per rendere JavaScript più appetibile a programmatori che vengono da altri linguaggi realmente class-based.

 

*ES6 – acronimo di ECMAScript 6 – è stata rilasciata a giugno 2015, e oggi vede un livello di implementazione da parte dei produttori dei Browser sufficientemente avanzato da spingere gli sviluppatori ad abbracciarne l’adozione nel proprio codice.