Programmazione Object Oriented in JavaScript

Socrate diceva: “Più so, più so di non sapere”. Ed è vero… Man mano che si impara (e nella vita si impara sempre), più dubbi ci vengono sulle nostre conoscenze ed io, sebbene sapessi che con JavaScript si potesse “programmare ad oggetti” (in senso lato) e ne avessi una vaga idea, non mi ero mai posto il problema di scoprire come in realtà si facesse. Ho deciso di colmare questa mia lacuna e ora riporto i miei appunti qui.

Chiunque viene dal mondo della programmazione ad oggetti ha familiarità con i concetti di tipo, tipo di dati astratto, classe, ereditarietà tra classi e così via. In JavaScript ci sono diversi modi di programmare ad oggetti; uno di questi modi fa uso del “prototype pattern” e con un esempio (per chi conosce la OOP) è bello che spiegato.

function Persona() {
  this.nome= "";
  this.eta= 15;
}

Persona.prototype.setNome = function(_nome) {
  this.nome= _nome;
}

Persona..prototype.setEta = function(_eta) {
  this.eta = _eta;
}

var nicola = new Persona();
nicola .setNome ("nicola");
nicola .setEta (25);
alert(nicola.nome + " - " + nicola.eta);

per ereditare la classe Persona

function Maschio() {
  this.sesso= "M";
}

Maschio.prototype = new Persona();

function Femmina() {
  this.sesso= "F";
}

Femmina.prototype = new Persona();

questa modalità di implementazione delle classi è quella consigliata quando si lavora con AJAX. Da notare è che si può scrivere anche:

function Persona() {
  this.nome= "";
  this.eta= 15;

  Persona.prototype.setNome = function(_nome) {
    this.nome= _nome;
  };

  Persona..prototype.setEta = function(_eta) {
   this.eta = _eta;
  };
}

in questo caso, però, il trucchetto dell’ereditarietà non funziona.

L’altro modo per scrivere una classe è quello che ho trovato utilizzato in YahooUI e in jQuery (e nello spezzone di codice dell’articolo precedente) e di cui allego un esempio che dovrebbe essere abbastanza comprensibile:

<html>
  <head>
  <script>
  p = {
    pippo : 'ciao',
    prova_var: 1,
    prova: function() {
             alert(this.pippo + ' - ' + this.prova_var);
    }
  };
  </script>
  </head>
  <body>
    <input type="button" value="bottone" onclick="p.prova()" />
  </body>
</html>

è una notazione cha sa di JSON e infatti è basata su quella JSON; definisce l’oggetto già come singola instanza: infatti, come si vede, lo utilizzo tranquillamente nel codice HTML.

Questo è solo qualche appunto, ma per approfondimenti contattate il vostro motore di ricerca di fiducia 😉

P.S.: Recentemente ho trovato questo link che sipega tutte le notazioni: http://www.phpied.com/3-ways-to-define-a-javascript-class/

JavaScript e Distributed Computing

Su Hacker Journal n°173 è comparso un articolo interessante intitolato “La potenza del Browser”, il quale ha particolarmente attirato la mia attenzione.

L’idea alla base dell’articolo è di usare JavaScript per l’elaborazione distribuita lato client. Un piccolo script ciclicamente richiede al server la parte di lavoro da effettuare, effettua la sua elaborazione ed invia la risposta al server, il tutto durante la navigazione sul sito, senza influire sulla qualità percepita dall’utente.

L’articolo propone come esempio il sito http://jsdc.appspot.com/. Proviamo a comprendere cosa fa questo script, commentando il codice sorgente.

_d = {
 //indirizzo della pagina del server che distribuisce 
 //il carico di lavoro e le risposte
 eh: “http: //jsdc.appspot.com/Q?”,

 //timeout iniziale (di default)
 iv: 150,

 //funzione da richiamare
 f: hex_md5,
 o: 9,
 “cap interval”

 //timeout corrente
 z: 150,
 n: 0,

 //ritorna semplicemente la data
 w: function() {
 return (new Date()).getTime()
 },

 // elabora il pacchetto di lavoro
 u: function() {
 var x = _d.w(),

 //_d.d sono le parole da convertire in MD5 (passate dal server)
 e = _d.e + _d.d[_d.n],
 i = 0;

 //adatta il carico di lavoro al client
 if (x - _d.y - _d.z < _d.o)
 _d.z = _d.iv
 else
 _d.z = x - _d.y;

 if (_d.n < _d.d.length) {
 //scorro l’array del carico di lavoro
   for (; i < _d.d.length; i++) {

      //elaboro le singole parole e confronto con l’hash 
      //passato dal server
      if (_d.f(e + _d.d[i]) == _d.h) {
        _d.v = e + _d.d[i];
 
        //inoltro la richiesta con l’ apposita funzione b()
        _d.b();
        return;
      }
   };
 
   _d.n++;
   _d.y = _d.w();

   //prossimo ciclo
   _d.x = setTimeout(_d.u, _d.z)
 } else {
   //effettuo la richiesta del primo carico di lavoro
   _d.b()
 },

 //funzione che effettua la richiesta
 g: function(u) {
    alert(u);

    //creo un elemento dom script
    _d.q = document.createElement(“script”)

    //imposto come src dell’ elemento script la pagina del server
    //che fa il dispatch delle richieste e accumula le risposte
    _d.q.src = _d.eh + u;

    //aggiungo al body il nuovo tag
    document.body.appendChild(_d.q)
 },

 //funzione che compone la richiesta
 b: function() {
    //fermo il timer
    _d.cs()

    //compongo per la funzione che effettua la richiesta 
    //i parametri del GET
    _d.g(“e = ”+_d.e + ” & h = ”+_d.h + ” & r = ”+_d.v + ” & ”+_d.w())
 },

 //ferma il timer e dunque sospende l’ elaborazione
 cs: function() {
     clearTimeout(_d.x);
     _d.x = null;
     _d.n = 0
 }

}

//inizializza l’ elaborazione senza parametri
//(prima richiesta del carico di lavoro)
setTimeout(_d.g, 2000);

La risposta del server contiene i dati da elaborare in background ed il codice necessario per avviare l’elaborazione; tale risposta viene scritta nel tag “script” generato dinamicamente e, dunque, eseguita. Commentiamo il codice della risposta:

//eliminiamo il tag script appena creato, in modo da
//non averne tanti
_d.q.parentNode.removeChild(_d.q);
_d.i=3200;

//il carico di lavoro: le stringhe di cui provare l’hash md5
_d.d=’ole ala apo 123 ddd ff ttt rot oleole’.split(”);
_d.d.push(”);

//l’hash md5 di riferimento
_d.h=’b52f753aa106a9df6a51248744fc464f’;
_d.e=’l d’;

//parametri necessari per la temporizzazione
_d.y=_d.w()-_d.z;

//richiamo la funzione che elabora il pacchetto di lavoro
_d.u();
_d.v=undefined;

Dopo l’elaborazione, al server viene inviato il risultato. Tale operazione viene portata a termine tramite una richiesta GET HTTP che ha come parametri: la variabile “h”, che contiene l’md5 che si sta esaminando e la variabile “r” che contiene l’eventuale risultato (che è in _d.v).

Spero che i miei commenti vi abbiano aiutato nella comprensione dello script e, magari, ispirato qualche bella idea. Anche se tutto il codice non è proprio chiaro, il meccanismo alla base è davvero semplice e (sorprendentemente) non fa uso di AJAX. Vi lascio con l’avvertimento che si può trovare sul sito: questo codice è un proof of concept, instabile e vulnerabile ad attacchi XSS.