Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26

    Getter and setters: questi sconosciuti [EcmaScript5/oop]

    Visto che sto facendo un'estensione ho tutto di diritto di mandare a quel paese IE e di leggere solo e soltanto il mozilla developer network

    Comunque, ho scoperto da poco queste magnifiche caratteristiche di ES5, ovviamente già supportate da gecko, ovvero il setter ed il getter. Il problema è che non riesco proprio a trovare un metodo per conciliare getter e setter con le variabili private di classe. Un esempio vale più di mille parole:

    codice:
    var Macchina = function (targa) {
       this.targa = targa; // accede al setter!
       var _targa;
    }
    
    Macchina.prototype = {
       get targa() { return _targa; }
       set targa(value) { _targa = value.length < 8 ? value : null }
    };
    ed ora , semplicemente,
    codice:
    var auto = new Macchina('AY123YY');
    alert(auto.targa)
    ovviamente non funziona niente. (auto.targa è undefined, l'assegnazione non riesce)
    Macchina.prototype non può accedere alle variabili private. C'è qualche metodo per aggirare questa limitazione? Sto cercando da tre giorni! Grazie

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26
    Ho trovato la soluzione!

    Ironia della sorte proprio pochi minuto dopo essermi deciso a chiedere

    codice:
    function Macchina() {
        var _targa = 'ciao';
        this.targa setter = function(value) { _targa = value; }
        this.email getter = function() { return _targa; }
    }
    Finalmente ho ritrovato la felicità

  3. #3
    Quella è una soluzione. Però attento che così facendo ogni volta che fai una new Macchina() una copia dei tuoi setter e getter viene creata in memoria. Se invece li metti nel protototype ne esiste sempre e solo una copia sola. Non sono espertissimo di js, ma sto leggendo qualche libro e molta documentazione online, e questo è quello che ho letto.

    Inoltre in js non esiste il concetto di classe, ma solo di oggetto. E il fatto che tu faccia
    codice:
    var Oggetto = function() {
    var _prop;
    }
    Non significa che tu stia creando un'attributo privato della classe Oggetto. Quello che stai facendo è sfruttare il concetto di closure: lo scope della tua variabile _prop è la funzione Oggetto e le funzioni definite all'interno di essa, ragion per cui riesci ad accedervi se definisci setters e getters con il this all'interno della funzione stessa.

    Quello che potresti fare per avere un codice più efficiente è qualcosa del genere:

    codice:
    var Oggetto = (function() {
    var _prop;
    
    var _OggettoClass = function (p) {
      _prop=p;
    }
    
    _OggettoClass.prototype.getProp = function() {
     return _prop;
    }
    
    _OggettoClass.prototype.constructor = Oggetto;
    
    return _OggettoClass;
    }());
    
    //a sto punto puoi fare
    
    var o = new Oggetto();
    Sarebbe interessante una discussione su questo, quindi aspetto il parere dei più esperti.
    max

    Silence is better than bullshit.
    @mmarcon
    jHERE, Maps made easy

  4. #4
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26
    Grazie per le precisazioni, sempre utili ovviamente, però mi sento di discolparmi : l'ho chiamata classe per semplicità usando un abuso di forma, pur sapendo che in js non esistono classi ma "qualcosa che si comporta come tale".

    Però sinceramente non ho capito il vantaggio del tuo codice. Stai parlando per caso in termini prestazionali?

    Sinceramente ho trovato documentazione un po' scarsa in questo ambito... se hai qualche riferimento interessante sarei felicissimo se lo condividessi

    Grazie mille, ogni consiglio è prezioso, anche per chiarirmi un po' le idee, sto cercando di togliermi completamente quei residui di programmazione procedurale dalla testa, e se con altri linguaggi è stato facile javascript tutto sommato mi sta dando qualche problema!

  5. #5
    Mi riferivo in termini prestazionali sì.

    Mah sicuramente un buon libro che spiega quella e tante altre cose è javascript patterns della oreilly. Trovo che sia ben fatto.

    Ma di sicuro come ho già detto sarebbe bello intraprendere una discussione con altri utenti esperti.
    max

    Silence is better than bullshit.
    @mmarcon
    jHERE, Maps made easy

  6. #6
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26
    Problemi in vista. Sì, funziona tutto e bene, ma The Online Lint mi dice per ogni getter/setter che sia:

    codice:
          ======================^
          warning: deprecated setter usage
    Quindi non si usa più. Ovviamente in rete non trovo niente. Qualcuno dall'alto della conoscenza dei nuovi standard js potrebbe illuminarmi? mxa tu ne sapevi niente?? Ho appena finito di aggiornare 4000 righe di codice, se si scopre che è veramente così deprecato come dice il lint ti riterrò direttamente responsabile

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2010
    Messaggi
    3,660
    Originariamente inviato da whiles
    Ho trovato la soluzione!

    Ironia della sorte proprio pochi minuto dopo essermi deciso a chiedere

    codice:
    function Macchina() {
        var _targa = 'ciao';
        this.targa setter = function(value) { _targa = value; }
        this.email getter = function() { return _targa; }
    }
    Finalmente ho ritrovato la felicità


    questa non mi sembra affatto la soluzione corretta, come fai a dire che funziona? e come li richiami i metodi getter e setter?
    Per quanto ne so ci sono svariati modi per creare i metodi getter e setter ma il tuo non mi pare corretto.

    codice:
    function Macchina(val){
    	this._targa = val;
    }
    
    Macchina.prototype = {
    	get targa(){
    		return this._targa;
    	},
    	set targa(val){
    		this._targa = val;
    	}
    };
    oppure usando i metodi definegetter e definesetter:

    codice:
    function Macchina(val){
        var targa = val;
        
        this.__defineGetter__("targa", function(){
            return targa;
        });
        
        this.__defineSetter__("targa", function(val){
            targa = val;
        });
    }
    o ancora utilizzando direttamente il metodo defineProperty dell'oggetto Object

    codice:
    function Macchina(val){
        var targa = val;
        
        Object.defineProperty(this,"targa", {
            	get: function() {return targa;}
        });
        
        Object.defineProperty(this,"targa", {
            	set: function(val) {targa = val}
        });
    }

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26
    Vindav, ti posso dire con certezza che il metodo che ho scritto funziona bene, però solo su SpiderMonkey ed è il metodo che stilisticamente preferisco! (Non avrei mai cantato vittoria prima di provarlo)
    Quindi compatibilità solo con Gecko. I metodi li richiamo tranquillamente con i nomi delle proprietà: auto.targa .


    Comunque grazie per la rassegna dei metodi di definizione. __defineGetter__ e __defineSetter__ li conoscevo e li odiavo: tutti quegli underscore mi ricordano un listato di C

    Quello che non conoscevo invece era defineProperty, che mi sembra quello più stilisticamente appropriato e funzionale, peccato che però sia compatibile con javascript 1.8.5 (specifica di Firefox 4) e quindi non lo posso utilizzare .

  9. #9
    Utente di HTML.it
    Registrato dal
    Dec 2010
    Messaggi
    3,660
    questa non mi sembra affatto la soluzione corretta, come fai a dire che funziona? e come li richiami i metodi getter e setter?
    mi quoto da solo , ho visto ora che non hai creato il getter per targa ma per email, ed è per questo il risultato non mi tornava, cmq non conoscevo questa sintassi... c'è sempre da imparare

    Il primo esempio che ho postato? non ti piace? come mai l'hai scartato?


    Rispondendo invece a mxa:

    Quella è una soluzione. Però attento che così facendo ogni volta che fai una new Macchina() una copia dei tuoi setter e getter viene creata in memoria. Se invece li metti nel protototype ne esiste sempre e solo una copia sola. Non sono espertissimo di js, ma sto leggendo qualche libro e molta documentazione online, e questo è quello che ho letto.
    verissimo anche se la differenza di prestazioni credo non sia poi molta se non si prende in considerazione la costruzione di oggetti/classi molto complessi. In più si potrebbe andare a definire l'intero oggetto con prototype, per non utilizzarlo per ogni metodo. Credo cmq siano solo finezze.


    codice:
    function Macchina() {
        var _targa = 'ciao';
        this.targa setter = function(value) { _targa = value; }
        this.email getter = function() { return _targa; }
    }
    
    Macchina.prototype = new Macchina;


    var Oggetto = (function() {
    var _prop;

    var _OggettoClass = function (p) {
    _prop=p;
    }

    _OggettoClass.prototype.getProp = function() {
    return _prop;
    }

    _OggettoClass.prototype.constructor = Oggetto;

    return _OggettoClass;
    }());

    //a sto punto puoi fare

    var o = new Oggetto();
    [/CODE]
    Qua mi pare ci sia un errore invece, probabilmente di distrazione, la variabile prop è comune a tutte le istanze della "classe" Oggetto e quindi se modificata da un istanza creata, la modifica verra "vista" anche per un secondo oggetto instanziato. Es:

    codice:
    var o = new Oggetto("ciao");
    var o2 = new Oggetto("ciao2");
    alert(o.getProp()); //ciao2
    si risolve aggiungendo il this prima della variabile nel costruttore e nel metodo setProp.
    A parte questo il tuo esempio non credo rispecchi una creazione "dinamica" dei getter e setter ma semplicemente stai definendo un metodo che legge la variabile. La differenza tra qusto codice:

    codice:
    function Macchina(val){
        var targa = val;
        
        this.__defineGetter__("targa", function(){
            return targa;
        });
        
        this.__defineSetter__("targa", function(val){
            targa = val;
        });
    }
    e il tuo sta proprio nel fatto che ogni volta che io cerchero di accedere alla variabile targa( obj.targa) verrà effettuata una chiamata al metodo get associato, mentre nel tuo caso cerchera di accedere all' attributo dell'oggetto. Se ho detto troppe stronzate avvertitemi

    p.s. qui trovate una discussione molto interessante su svariati argomenti , compreso il prototype.

  10. #10
    Utente di HTML.it
    Registrato dal
    Dec 2007
    Messaggi
    26
    Ho scartato la soluzione che agisce sul prototype perchè non potevo agire su variabili definite con scope nel costruttore. Nel tuo caso voglio proprio evitare di creare una variabile accessibile dall'esterno, ovvero this._targa!

    All'inizio avevo le mie funzioni scritte con proprietà definite proprio in questo modo, però come soluzione mi sembrava abbastanza arrangiata (si lo so, dirai che sono fissato... ).

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.