giovedì 1 maggio 2014

Ulteriori sviluppi delle mie comprensioni del prototipo in JavaScript

In realtà, credo che se una variabile non viene inizializzata nel costruttore, di fatto non esiste.
Perché dunque non ottengo un messaggio di errore quando la mostro nell'Istanza?
Forse è semplicemente perché di fatto la aggiungo nell'istanza, non esistendo essa nel costruttore in quanto non inizializzata.
Forse questa "filosofia" è più aderente alla realtà.
function Oggetto(){
 this.prop;
}
var Istanza = new Oggetto();
alert(Istanza.prop);
Istanza.prop="Proprieta";
alert(Istanza.prop);
Ecco, in questo caso la proprietà non esiste nel costruttore, e la sintassi di definirla senza inizializzarla è praticamente sbagliata, in quanto non esiste e viene creata nell'istanza.
Ecco la creazione della proprietà prop in due istanze dell'oggetto:
function Oggetto(){
 this.prop;
}
var Istanza = new Oggetto();
var Istanza2=new Oggetto();
alert(Istanza.prop);
Istanza.prop="Proprieta";
alert(Istanza.prop);
Istanza2.prop="Proprieta dell'Istanza2";
alert(Istanza2.prop);
Ottengo i due valori di una proprietà che è stata creata indipendentemente nelle istanze, non nel costruttore!
Quindi quando io cerco di "cambiare" una variabile nel prototipo, sto piuttosto cercando di aggiungere una variabile che già esiste e quindi non posso sostituirla. Posso invece aggiungerla quando non c'è. Queste proprietà aggiunte nel prototipo possono essere modificate.
function Oggetto(){
 this.prop="Prima proprieta";
}
var Istanza = new Oggetto();
Oggetto.prototype.prop2="Seconda proprieta";
alert(Istanza.prop2);
Oggetto.prototype.prop2="Seconda proprieta modificata";
alert(Istanza.prop2);
Invece non possono essere modificate le proprietà presenti già nel costruttore:
function Oggetto(){
 this.prop="Prima proprieta";
}
var Istanza = new Oggetto();
Oggetto.prototype.prop2="Seconda proprieta";
alert(Istanza.prop2);
Oggetto.prototype.prop2="Seconda proprieta modificata";
alert(Istanza.prop2);
Oggetto.prototype.prop="Prima proprieta modificata";
alert(Istanza.prop);
La prima proprietà rimane sempre uguale a quella presente nel costruttore.

Trovata la regola di costruttore e prototipo

Quindi, il prototipo può modificare come vuole il costruttore, ma non se una proprietà è stata già inizializzata nel costruttore stesso.

Forse sto cominciando a capire bene qualcosa...

Proprietà aggiunte nel prototipo e proprietà inizializzate nel costruttore: differenza.

Ecco, forse sto arrivando a capo del segreto...

Adesso inizializzo una proprietà nel costruttore e poi la modifico nel prototipo
function Oggetto(){
 this.prop="Prima proprieta";
}

var Istanza=new Oggetto();

alert(Istanza.prop);

Oggetto.prototype.prop="Prima proprieta modificata";

alert(Istanza.prop);
Ottengo: Prima proprieta e Prima proprieta.

La proprietà inizializzata nel costruttore non può più essere modificata nel prototipo.
Ora invece di inizializzarla nel costruttore la inizializzo nel prototipo:
function Oggetto(){

}

var Istanza=new Oggetto();

Oggetto.prototype.prop="Prima proprieta";

alert(Istanza.prop);

Oggetto.prototype.prop="Prima proprieta modificata";

alert(Istanza.prop);
E ottengo Prima proprieta e Prima proprieta modificata.
Dunque, la proprietà che non è stata inizializzata nel costruttore può essere modificata nel prototipo.
Per questo, se ho aggiunto una proprietà nel prototipo, posso poi modificarla.
function Oggetto(){
 this.prop="Prima proprieta";
}

var Istanza=new Oggetto();



alert(Istanza.prop2);

Oggetto.prototype.prop2="Seconda proprieta";

alert(Istanza.prop2);

Oggetto.prototype.prop2="Seconda proprieta modificata";

alert(Istanza.prop2);
ottenendo rispettivamente: Nulla, Seconda proprieta e Seconda proprieta modificata.
Non ci sto capendo più niente!!!!!
Se invece aggiungiamo una proprietà nel prototipo, tutte le istanze, anche quelle già create, assumono questa proprietà.
function Oggetto(){
 this.prop="Prima proprieta";
}

var Istanza=new Oggetto();


alert(Istanza.prop2);

Oggetto.prototype.prop2="Seconda proprieta";

alert(Istanza.prop2);
Ottengo un alert vuoto (prima che nel prototipo venga aggiunta l'altra proprietà) e poi un alert che mostra "Seconda proprieta".
Dunque, se nel prototipo la variabile non è stata inizializzata, può essere successivamente modificata, mentre se è stata inizializzata non può essere modificata.
L'istanza prende la proprietà pari pari dal costruttore, e non può essere modificata se non dalla stessa istanza.
Solo se la proprietà non è stata definita dal costruttore può essere modificata.
Ecco la regola.

Prototipi e proprietà

Dunque le istanze prendono i valori delle proprietà dal prototipo, a meno che questi valori non vengano definiti nell'istanza.
Faccio la prova.
function Oggetto(){
 this.prop;
}

var Istanza=new Oggetto();


alert(Istanza.prop);

Oggetto.prototype.prop="Proprieta definita nel prototipo";

alert(Istanza.prop);
  1. Per prima cosa, creo un'Istanza.
  2. Mostro il valore della proprietà.
  3. Modifico il valore della proprietà nel prototipo.
  4. Mostro di nuovo il valore della proprietà
La prima volta ottengo un valore nullo, la seconda volta ottengo "Proprieta definita nel prototipo".
Adesso do direttamente un valore nel costruttore:
function Oggetto(){
 this.prop="Prima definizione nel prototipo";
}

var Istanza=new Oggetto();


alert(Istanza.prop);

Oggetto.prototype.prop="Seconda definizione nel prototipo";

alert(Istanza.prop);
In questo caso, la proprietà è sempre uguale a "Prima definizione nel prototipo".

Perché???