Premesso che non son un drago con la programmazione ad oggetti che si fonda sui prototipi (quindi andateci piano con le spiegazioni ^_^ per lo meno tenete conto che potrei non afferrare tutto subito), mi domandavo come si potesse in javascript risalire alla "classe" che ha generato un istanza (e alcune altre cose).
Mi spiego, raccontandovi quel che ho fin ora capito e cosa abbia fatto.
Dunque mi pare di capire che in javascript non esistano realmente classi ma solo istanze che nascono da altre istanze con un processo di decorazione degli oggetti chiamato prototipazione (e fin qui grosso modo credo di esserci).
Quando si scrive quello che io chiamo "classe"
es :
function MiaClasse ( parametriCostruttore )
{
this.attributoPubblicoSettatoNelCostruttore = parametriCostruttore ;
}
In realtà si instanzia un oggetto di tipo function che viene creato come "litteral" dalla funzione che abbiamo scritto prima.
Pertanto sarà dotato di attributi particolari come il .name che le altre funzioni non dovrebbero avere.
(ecco questo mi è particolarmente difficile da capire, cosa abbia questa definizione di differente per il compilatore da una this.mioMetodo = function miaFunzione () {} ; )
Dato che l'istanza generata non è assegnata a nessuna variabile finisce agganciata allo scope globale con il nome della funzione e per questo si comporta come se fosse una "classe" (da un punto di vista concettuale) pure essendo un istanza, e può essere usata per creare altre istanze.
(ok anche questo mi è piuttosto fumoso e poco chiaro)
Ora le mie domande sono :
Il debugger di chrome data un istanza genera una descrizione che di fatto indica quale classe l'abbia generata.
Mi spiego , se faccio qualcosa del tio
function Persona () {}
var miaPersona = new Persona () ; // nel debugger se nelle watch expression scrivo miaPersona alla sua sinistra compare la scritta " : Persona" che è il nome della classe che l'ha generata.
Con miaPersona.constructor.name si potrebbe pensare di aver raggiunto l'obiettivo, ma c'è il problema che se il tipo dell'oggetto non è semplice (ma ricorre ad ereditarietà) il constructor punta all'oggetto sbagliato nella catena dei prototipi (in particolare al primo) e quindi non otterrei il risultato che voglio.
es
function Vivente () {}
function Animale () {}
function Persona () {}
Animale.prototype = new Vivente() ;
Persona.prototype = new Animale () ;
var miaPersona = new Persona () ;
miaPersona.constructor.name \\ Vivente e non Persona
Desidero fare questo perché sto scrivendo una funzione per fare il deepCopy di un istanza, e quando devo creare l'istanza copia vorrei crearla dello stesso "tipo" dell'istanza di origine.
Ok che i tipi non esistono e che ogni istanza può essere stravolta a runtime in modi impredicibili ed incontrollabili, però quanto meno per comodità mia in giro nel codice vorrei fare nel mio piccolo un po di type checking per avere qualche garanzia in più (pertanto non posso permettermi di creare l'istanza a partire da Object e poi aggiungervi le proprietà perché poi non risulterebbe del "tipo" corretto).
Quindi se riuscissi ad ottenere la classe che ha generato l'istanza potrei generare una nuova istanza da essa.
Mi accontenterei anche solo di generare un istanza a partire da un altra; di modo che la nuova istanza venga creata dalla prima allo stesso modo con cui la prima è stata creata dalla "classe" che l'ha generata.
Ps : vorrei evitare di utilizzare l'oggetto JSON.stringify e JSON.parse per clonare gli oggetti, non metto in dubbio che sia sicuramente più efficace di qualsiasi cosa possa scrivere io (in termini di tempo impiegato) ma oltre a perdere il "tipo" cosa che mi scoccerebbe, rischia di generare eccezioni qual'ora vi fossero referenze circolari tra più oggetti contenuti nell'oggetto da clonare.
Allo stesso modo vorrei evitare di mettere nel prototipo della "classe" Object una proprietà da popolare con il nome della classe, di modo da suggerirmelo in futuro, questo perché ho paura possa essere una grande limitazione qual'ora volessi integrare oggetti di terze parti su cui non ho il controllo (e di cui non posso popolare il campo che poi dovrebbe suggerirmi il nome della "classe").
PPs :
Ho trovato un articolo Fixing the JavaScript typeof operator | JavaScript, JavaScript... che
propone di modificare il prototipo della "classe" Object per accedere alla proprietà privata [[class]] che dovrebbe contenere le informazioni che mi interessano.
Probabilmente avrò capito male quel che c'è scritto nell'articolo, ma non riesco a fare una cosa simile seguendo le sue istruzioni, qualcuno mi potrebbe spiegare esattamente cosa intende (magari con un esempio di codice) quando spiega come modificare il prototipo ?
Che se io provo a modificare il prototipo della "classe" Object come mi è parso di capire (ossia scrivendo prima o dopo la parola [[class]] o anche solo class) ottengo come eccezione (ancora prima di eseguire) che ho usato una keyword riservata nel codice (ossia la parola class appunto che pare non si possa scrivere).
PPPs : (ok dopo questo prometto ho finito)
Sempre in un modo analogo a quello illustrato dall'articolo (sempre che alla fine sia realizzabile) e considerando che tutte le istanze in un qual modo sono figlie di Object() mi domandavo se non si potesse (modificando solo il prototype di quest'ultima "classe" un unica volta) accedere a tutte le proprietà private (qualsiasi esse siano) di una qualsiasi istanza (non credo ne, ma preferisco avere anche la conferma da qualcuno più esperto).
Mille grazie in anticipo per le risposte ma soprattutto per la pazienza =)


LinkBack URL
About LinkBacks
Rispondi quotando
