JavaScript è probabilmente il linguaggio di scripting più popolare sul web: è merito di JavaScript e CSS se le pagine visualizzate all'interno del browser possono prendere vita, ovvero diventare dinamiche. Non a caso si parla di Dynamic HTML per indicare quell'insieme di tecnologie che rendono interattivo il web, tra cui spiccano JavaScript, CSS e alcune caratteristiche del DOM.

Nonostante la sua popolarità, la capacità di JavaScript di creare classi ed oggetti conformi al paradigma di programmazione OOP (Object Oriented Programming) è poco conosciuta o poco sfruttata. Un motivo è che molti web designers si approcciano all'HTML con un bagaglio di conoscenze orientate al web, senza un background di programmazione “classico” tipico di chi proviene da C++ o Java. Chi conosce bene la programmazione OOP a volte considera JavaScript come un “giocattolino”, e non prende sul serio le potenzialità della programmazione ad oggetti in questo contesto.

Oggi cercheremo di introdurre l'argomento ai neofiti, e contemporaneamente di invogliare i più esperti a considerare meglio l'OOP nell'ambito JavaScript.

Strumenti di lavoro

Un modo pratico di sperimentare l'OOP con JavaScript è quello di utilizzare il plugin Firebug di Firefox, che permette di lavorare con la console del browser un po' come a riga di comando, senza preoccuparci di visualizzare i risultati usando document.write() o gli scomodissimi alert(). Come prima cosa scriviamo una funzione per loggare i risultati dei nostri esperimenti

function logMessage(msg) {

if (firebug) console.log(msg) ;

else document.write(msg + "<br/>") ;

}

In questo modo potremo scrivere var firebug=true oppure var firebug=false all'interno della tag script, per rendere cross-browser il codice da sperimentare.

Primi oggetti

Bando alle ciance e vediamo subito un esempio di oggetto JavaScript

function dog(name) {

this.name = name;

this.speak = function() {

return (this.name + " barking!")

}

}

qui sopra abbiamo definito una classe dog, avente un attributo (name) e un metodo (speak) , che vedremo presto come usare. La definizione ci permette di creare quanti oggetti vogliamo, ad esempio

dog1 = new dog("Scooby-Doo");

dog2 = new dog("Rin Tin Tin");

i due oggetti dog1 e dog2 avranno quindi un valore diverso per l'attributo name, perché i valori passati al momento di costruire l'oggetto sono diversi (“Scooby-Doo” e “Rin Tin Tin”), ma saranno tutti istanze (cioè rappresentanti) della stessa classe dog.

Per verificarlo ci basterà scrivere

logMessage( dog1.speak() );

logMessage( dog2.speak() );

dove stiamo assumendo di aver scritto la funzione logMessage() suggerita all'inizio di questo articolo. Questo semplice esempio dovrebbe aiutarci a capire se e quando valutare l'uso dell'OOP all'interno di una pagina web.

Il criterio principale potrebbe essere il seguente: se una collezione di funzioni e/o attributi va ripetuta più volte all'interno dello stesso contesto, presentando comportamenti simili e parametrici, allora può risultare comodo “incapsulare” la collezione in un oggetto.

In parole più semplici: finché il comportamento di alcune funzioni JavaScript è completamente determinato dai parametri passati come argomento delle funzioni, possiamo fare a meno dell'OOP. Se invece il comportamento della funzione dipende anche da variabili più o meno stabili, che solitamente vengono definite come var direttamente all'interno della tag script (e non all'interno di qualche funzione), allora dobbiamo chiederci se alcune di queste variabili andrebbero “embeddate” in un opportuno oggetto come attributi dell'oggetto stesso.

Per chiarire il concetto consideriamo un'alternativa al codice scritto sopra

var dog_name_1 = "Scooby-Doo";

var dog_name_2 = “Rin Tin Tin”;

function speak(name) {

return (name + " barking!");

}

logMessage( speak(dog_name_1) );

logMessage( speak(dog_name_2) );

qui otteniamo lo stesso risultato, ma senza ricorrere all'OOP. In questo caso i due approcci sono praticamente equivalenti, anzi, forse è più semplice la soluzione tradizionale, che non richiede la creazione di alcun oggetto. Le cose potrebbero cambiare se il comportamento (o meglio l'implementazione) del metodo speak dipende da molte variabili, e non da una sola come nel caso considerato. Se l'implementazione di un metodo riflette la complessità di un insieme di variabili, e se quella collezione di variabili deve essere “clonata” con diversi valori, allora può risultare vantaggioso raggruppare variabili e metodi in un oggetto. Consideriamo ad esempio

function sprite(x, y) {

this.the_x = x ;

this.the_y = y ;

this.animate = function() { //cambia le coordinate x,y }

}

dove stiamo assumendo che il metodo animate() si occupi di gestire un'animazione, modificando gli attributi x e y. In questo caso, se la nostra pagina deve animare molti oggetti contemporaneamente, potrebbe risultare conveniente avere un oggetto dedicato per ogni singola animazione, che potrebbe così seguire un iter diverso caso per caso.

Come tutti gli strumenti, anche l'OOP non è una soluzione obbligatoria, sta a noi valutare caso per caso se conviene o se non è necessaria. E' quindi bene ricordasi della sua esistenza, per avere uno strumento in più nella cassetta degli attrezzi.