+ Rispondi al Thread
Visualizzazione dei risultati da 1 a 3 su 3

Discussione: Javascript Oggetti e [[class]]

  1. #1
    Skary non è in linea Scolaretto
    Post
    331

    Javascript Oggetti e [[class]]

    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 =)
    Ultima modifica di Skary; 18-03-2013 22:36 

  2. #2
    L'avatar di bumm
    bumm non è in linea Very Important Person Ultimo blog: [VB2010] ComboBox ed Enumeratori
    Luogo
    Bologna
    Post
    1,950
    Blogs
    1
    Hai la possibilità di usare jQuery? In quel caso per fare DeepCopy puoi utlilizzare $.extend(...)
    "HeloWorld.exe" 17 errors, 31 warnings.

    Non mi mandate le richieste di aiuto via PM! Non vi risponderò! Tutte le domande fateli sul forum!

  3. #3
    Skary non è in linea Scolaretto
    Post
    331
    Mha veramente stavo scrivendo io una raccolta di funzioni utili, una piccola libreria, ed avrei preferito limitare al massimo le dipendenze.

    Tra l'altro ho paura che questo deep copy di jquery (ma devo ancora provare) non faccia altro che copiare in modo "profondo" le proprietà di un oggetto su un altro.

    La domanda è se l'oggetto varA è istanziato sulla classe Casa che eredita da Edificio, e io ne effettuo una copia profonda sulla variabile chiamata varB, avrò che varB instanceof Casa = true (devo verificare) ?
    Questo è quello che vorrei preservare scrivendo la mia funzione di deep copy e che al momento non riesco a fare.
    Da qui l'idea di accedere al nome della classe che ha generato l'oggetto da copiare.

    Grazie ancora per la pazienza di seguire i miei problemi, che potrebbero sembrare balzani (e forse lo sono), ma vorrei reciclare del codice per validare gli input delle funzioni (una sorta di assert) che effettua del type checking.

    Ps :
    Riflettendo su quel che ti ho scritto prima mi è venuta in mente una cosa.
    Ossia se copiando "profondamente" anche la catena di prototipazione non si ottenesse esito positivo da un test con instanceof.

    Ho fatto una prova ed ho ottenuto :
    codice:
    function Building () { this.name="building" }
    function House () { this.par="ciao"}
    
    var myBuilding = new Building() ;
    House.prototype = myBuilding ;
    
    var house = new House () ; 
    var obj = new Object() ;
    var obj1 = new Object () ;
    obj.__proto__ = house.__proto__ ;
    
    alert ( obj instanceof House ) ;
    alert ( obj1 instanceof House ) ;
    Sembrerebbe quindi fare al caso mio.
    Mi sapresti dire se il mio ragionamento è fallace ? (tieni presente però che i limiti di instanceof non mi interessano li reputo sufficienti per verificare se un oggetto è stato istanziato da una classe, poi se instanceof proviene da un altra window e quindi fallisce anche se dovrebbe aver successo non mi importa).

    Eventualmente potrei anche risolvere così o ho dimenticato qualcosa ?

+ Rispondi al Thread

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi