JavaScript: dettagli implementativi del pattern klass

JavaScript: dettagli implementativi del pattern klass

JavaScript, a differenza di altri linguaggi object-oriented come PHP, non ha il concetto di metodi di inizializzazione di un oggetto (o classe, se vogliamo utilizzare la tradizionale definizione in uso presso altri linguaggi). I metodi e le proprietà di un oggetto vengono rese accessibili tramite la proprietà prototype, che è, anche secondo le specifiche ECMAScript, il veicolo attraverso cui l'ereditarietà ha luogo in JavaScript. Sulla scia del successo avuto dalla libreria Prototype, molti sviluppatori utilizzano un pattern simile a quello di questa libreria chiamato klass. Vediamone insieme i dettagli.

Creare oggetti

Il pattern klass utilizza un metodo helper per la creazione di oggetti ed istanze:


if (typeof Object.create !== 'function') {
    Object.create = function(o) {
      function F() {}
      F.prototype = o;
      return new F();
    };
}

Questo metodo, chiamato create(), è basato su un pattern originariamente creato da Douglas Crockford e prevede l'uso di un oggetto intermedio che viene legato all'oggetto da creare tramite la proprietà prototype. In questo modo l'oggetto da creare diventa il prototype dell'oggetto intermedio che viene poi inizializzato tramite l'operatore new.

Definire klass

klass viene definito con un metodo di inizializzazione associato a prototype:


var Klass = {
  init: function(){},

  prototype: {
    init: function(){}
  },
  
  // continua
};

Un oggetto letterale in JavaScript ha come tutti gli altri una proprietà prototype associata, ma a differenza delle funzioni questo tipo di oggetti ha una proprietà prototype di tipo undefined quando viene creato. Quindi occorre esplicitamente definire questa proprietà come oggetto.

All'interno di tale oggetto viene definito il metodo init(), lasciato vuoto per permettere a ciascun oggetto creato tramite Klass di definire i suoi membri:


var MyClass = Klass.create();

MyClass.init = function() {

	this.test = 'Test';

};


console.log(MyClass.test); // 'Test'

Il prossimo passo è quello di associare il metodo create() a Klass:


var Klass = {
  init: function(){},

  prototype: {
    init: function(){}
  },

  create: function(){
    var object = Object.create(this);
    object.parent = this;
    object.init.apply(object, arguments);
    return object;
  }
};

Questo metodo usa il metodo create() aggiunto ad Object per creare un nuovo oggetto a partire da quello corrente:


var object = Object.create(this);

this si riferisce all'oggetto corrente, nel nostro caso a MyClass. L'inizializzazione avviene effettivamente quando il metodo init() viene invocato sull'oggetto corrente con i suoi argomenti (l'array arguments):


object.init.apply(object, arguments);

parent è una proprietà che conserva il riferimento originario all'oggetto corrente e può essere usata quando vogliamo accedere ad un oggetto genitore all'interno di un oggetto figlio.

In pratica quello che succede in questo caso è analogo al seguente codice PHP:


class B extends A
{
    public function __construct() 
    {
    
    	parent::__construct();
    
    }
}

Abbiamo quindi simulato la parola chiave parent che non esiste in JavaScript.

Torna su