Domanda

Dopo aver letto un po 'il modello di ereditarietà prototipo di Javascript, cambio il mio stile di costruzione di una classe da

var Some_Class = function() {
    this.public_method = function() {
    };
    (function() {
        // constructor
    }).call(this)
}

a

var Some_Class = function() {
    (function() {
        // constructor
    }).call(this)
}
Some_Class.prototype.public_method = function() {
};

Anche se capisco che questa è una buona pratica, ma non mi è più permesso accedere ai metodi privati ??dal metodo pubblico

var Some_Class = function() {
    var private_member = 'whatever';

    (function() {
        // constructor
    }).call(this)
}
Some_Class.prototype.public_method = function() {
    return private_member; // not possible
};

Dopo aver letto un articolo qui (costruttore creato dalla chiusura), poi sono uscito con questo

var Some_Class = function() {
    var private_member = 'whatever',

    private_method = function(_some_value) {
        // private method implementation
    };

    if(!arguments.callee.prototype.public_method) {
        arguments.callee.prototype.public_method = function() {
            private_method.call(this, private_method);
        };
    }

    (function() {
        // constructor
    }).call(this)
}

Tuttavia, quali sono gli svantaggi di farlo ?! o c'è un modo migliore per farlo se voglio accedere a membro privato in pubblico metodo?

È stato utile?

Soluzione

L'uso di variabili e chiusure dell'ambito delle funzioni per simulare variabili / funzioni private è un linguaggio consolidato nella comunità javascript. Se la variabile è davvero destinata a essere privata, non vedo alcun inconveniente di questo approccio (anche se alcuni sostengono che il codice performante su alcuni browser / host debba prestare attenzione a quante chiusure vengono create).

Nel tuo esempio, private_method (e il suo ambiente) è condiviso su tutti gli oggetti - poiché la tua chiusura public_method viene creata solo la prima volta che l'oggetto viene costruito (e associato alla proprietà prototipo del costruttore che imposta la catena di prototipi interna dell'oggetto creato ) - quindi il metodo privato utilizzato è solo quello creato la prima volta.

Ecco un codice di esempio che ti aiuterà a illustrare cosa sta succedendo:

  var global = 1;

  var Some_Class = function() {
    var private_method = 'whatever';
    var now = ++global;
    print("outer now: " + now );
    private_method = function(_some_value) {
        // private method implementation
        print("inner now: " + now);
    };

    if(!arguments.callee.prototype.public_method) {
        arguments.callee.prototype.public_method = function() {

            private_method.call(this, private_method);
        };
    }

    (function() {
        // constructor
    }).call(this)
}

new Some_Class().public_method(); // outer now: 2, inner now: 2
new Some_Class().public_method(); // outer now: 3, inner now: 2
new Some_Class().public_method(); // outer now: 4, inner now: 2

Sei sicuro che sia quello che vuoi?

Se il tuo metodo privato non ha bisogno di fare riferimento allo stato dell'oggetto che racchiude, allora vedo pochi benefici nel fare le cose come stai facendo.

Quello che faccio di solito (se devo usare 'new' per creare il mio oggetto) è il seguente:

function MyClass() {
  var private_var = 1; 
  function private_func()
  {

  }
  this.public_func = function() 
  {
     // do something
     private_func();
  }
  this.public_var = 10;
}

var myObj = new MyClass();

Il rovescio della medaglia di questo approccio è che ogni volta che si costruisce l'oggetto tramite 'nuovo' si ricreano tutte le chiusure. Ma a meno che il mio profiler non mi dica che questa scelta progettuale deve essere ottimizzata, preferisco la sua semplicità e chiarezza.

Inoltre non vedo il vantaggio nel tuo codice di fare quanto segue:

  (function() { }).call(this);  // call the constructor

Perché stai creando un ambito separato nel tuo costruttore?

Altri suggerimenti

La mia risposta è una non-risposta: non c'è accesso privato incorporato in JavaScript ma va bene perché YAGNI . Ecco come faccio a rendere privati ?? nel mio codice:

function Some_Class() {
    this._private_member = 'whatever';
}

Some_Class.prototype._private_method = function() {
};

Va ??abbastanza bene. Non vale davvero la pena saltare attraverso i cerchi quando l'unico vero scopo di private è proteggerti da ... te stesso.

(Dico questo dopo aver trascorso molte ore me stesso giocando con ogni permutazione di chiusure e prototipazione, proprio come te, e infine dicendo " fanculo, non ne vale la pena " ;.)

Se non lo hai già fatto, dai un'occhiata a questo Modulo JavaScript Pattern , che consente di accedere a metodi e variabili privati ??all'interno delle funzioni pubbliche, ecc.

Facendo eco a John Kugelman: è impossibile creare membri privati ??in javascript. Convivici. Anche se crei un allegato come questo:

function SomeClass() {

   var _private = 0;
   this.public_acessor = function() {return _private};
}

Qualsiasi utente può ancora scrivere:

SomeClass._not_private_anymore = 1;
SomeClass.public_acessor = function () {return this._not_private_anymore}; 

Alla fine, non puoi fidarti che nessun membro pubblico sia lo stesso che hai dichiarato. Se qualcuno è pronto a infrangere il tuo codice, lo farà! Un altro utente non infrange il tuo codice solo perché è utile.

Funziona con prototipo, non solo singleton. Il problema è che, quando è il momento di sottoclassare, la mia sottoclasse non ha accesso ai privati ??

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top