ok, mi sono riletto poi e forse non è tutto chiaro ... proverò a spiegare quella che è definita sopra falsa eredità in modo migliore, poichè di falso non ha assolutamente niente, expected behaviour, sarebbe falso il contrario.
Ricominciamo da capo ... per avere una variabile privata, sono "costretto" a dover usare metodi privilegiati
codice:
function Pippo(){
var pippo = 123;
this.get = function(){
return pippo;
};
this.set = function(value){
pippo = value;
};
};
questi metodi, assieme alla variabile, hanno uno scope, che è il costruttore Pippo.
Non essendo metodi di prototype, vengono chiamati privilegiati, perchè ammesso scriva qualcosa tipo:
codice:
Pippo.prototype.get = function(){return 1};
ogni istanza di Pippo erediterà prima la prototype, poi la sua ridefinizione all'interno del costruttore.
codice:
alert((new Pippo).get()); // 123
Questa è l'eredità JavaScript 3rd edition, 1999 ... ai miei occhi non fa una piega, ma è differente da altri tipi di eredità, perchè gli altri tipi non si basano sui prototipi e non hanno concetti come metodi privilegiati.
Fino a qui è tutto chiaro? ... bene, passiamo oltre.
I metodi privilegiati sono diversi per ogni istanza.
codice:
var a = new Pippo,
b = new Pippo;
alert(a.get === b.get); // false
Questo comportamento è normale perchè ogni istanza avrà definiti runtime quei due metodi.
per farla breve, è come se scrivessi:
codice:
function Test(){};
var a = new Test,
b = new Test;
a.get = function(){return 1};
b.get = function(){return 1};
alert(a.get === b.get); // false
Quindi, tornando al costruttore Pippo, ogni istanza crea due metodi che lavorano in uno scope privato, dell'istanza, assieme alle variabili definite nello stesso scope, nel nostro caso, pippo.
Fin qui è tutto chiaro? 2 istanze, 4 funzioni create runtime più 2 variabli per 2 scopes differenti.
Questo è il motivo percui quando si vuole sfruttare JS al meglio, inteso come performances, è consigliabile usare l'ereditarietà senza privilegiati, che altro non fanno che overloadare i metodi di prototype (ho detto overloadare?
VVoVe: )
codice:
function Pippo(){
this.pippo = 123;
};
Pippo.prototype.get = function(){return this.pippo};
Pippo.prototype.set = function(value){this.pippo = value};
var a = new Pippo,
b = new Pippo;
alert(a.get === b.get); // true
a.set(456);
alert(a.get()); // 456
alert(b.get()); // 123
Bene, a questo punto possiamo anche fare una cosa di questo tipo:
codice:
// codice di prima
function Pluto(){};
Pluto.prototype = new Pippo;
var c = new Pluto,
d = new Pluto;
c.set(9);
alert(c.get()); // 9
alert(d.get()); // 123
alert(a.get()); // 456
alert(b.get()); // 123
alert(c instanceof Pippo); // true
alert(c instanceof Pluto); // true
alert(d.get === a.get); // true
Tutto ok? ... perfetto!
Torniamo all'anomalia che anomalia non è ... ripartendo da zero:
codice:
function Pippo(){
var pippo = 123;
this.get = function(){
return pippo;
};
this.set = function(value){
pippo = value;
};
};
Se con questo costruttore creo un'istanza, creerò automaticamente due funzioni più una variabile che appartengono a quella sola istanza.
codice:
var a = new Pippo;
A questo punto tutte le volte che scriverò
codice:
a.set(someValue);
è assolutamente naturale e logico che la variabile che andrò a mutare sarà quella pippo, di quello scope, di quella istanza ... una e sempre una.
Ok ??? bene ... ora cosa accade se assegno il tutto ad una prototype?
codice:
function Pluto(){};
Pluto.prototype = new Pippo;
La prototype in questione sarà un'istanza della classe Pippo con metodi privilegiati, ergo sarà tale quale la variabile a precedentemente istanziata.
Cosa significa? Significa che ogni istanza di Pluto avrà in prototype un'istanza di Pippo, con quella variabile, quelle due funzioni, appartenenti tutte ad un unico scope, di qui il divertimento del linguaggio, che non ha niente da rimpiangere, ma tanto di divertente e tanto ancora da imparare.
Ogni istanza di Pluto, quindi, utilizzerà i metodi di un'istanza di Pippo. Per fare un sunto, è come se scrivessimo esattamente questo
codice:
function Pippo(){
var pippo = 123;
this.get = function(){
return pippo;
};
this.set = function(value){
pippo = value;
};
};
var prototype = new Pippo;
function Pluto(){};
Pluto.prototype = prototype;
var p = new Pluto;
alert(p.get === prototype.get); // true
p.set(456);
var p2 = new Pluto;
alert(p2.get()); // 456
JavaScript, sei uno spettacolo, e raramente ho visto linguaggi più Object Oriented, sempre che questa frase abbia un senso ... buoni studi ed approfondimenti a tutti