7

EDIT: Alla fine ho capito dalla risposta di Bergi.Come creare un oggetto con membri privati ​​usando Object.create() invece di nuovo

Grazie Bergi.

pubPrivExample = (function() { 
    return { 
     init : function() { 
      var private; 

      this.setPrivate = function (p) { 
       private = p; 
      }; 
      this.getPrivate = function() { 
       return private; 
      }; 
     }, 

     public : "This is public\n" 
    }; 
}()); 

var a; 

a = Object.create(pubPrivExample); 
a.init(); 
a.setPrivate("This is private"); 

document.write(a.getPrivate()); 

EDIT: Sembra che le risposte alla mia domanda sono per la tangente. Non sono davvero interessato a una fabbrica e in realtà preferirei non usarlo se. La mia domanda riguarda lo stato privato. Dalle risposte e dai commenti di Bergi penso di poter tirare qualcosa insieme.

To be continued ...

EDIT: Bergi ha iniziato a rispondere alla domanda qui sotto, ma ha lasciato fuori la parte più importante - lo stato privato.

Ho avuto tempo di pensare ancora all'idea, ma non riesco ancora a raggiungere uno stato privato usando Object.create() senza una sorta di fabbrica. Ma voglio sbagliare, e Bergi ha accennato a una soluzione ... Sentiti libero di prendere la risposta di Bergi come punto di partenza.

ORIGINALE: La mia ricerca per evitare new in javascript mi ​​ha portato in un luogo particolare. Voglio membri di oggetti privati, ma non voglio rinunciare allo Object.create().

Ecco il codice.

var trackQueue = {}; 

trackQueue.factory = function() { 
    var that, queue; 
    that = this; 
    queue = []; 

    that.push = function (item) { 
     queue.push(item); 
    }; 

    that.work = function() { 
     document.write(queue + "<br />"); 
    }; 

    return { 
     work : that.work, 
     push : that.push 
    };   
}; 

var a = Object.create(trackQueue.factory()); 
a.push("a"); 
a.push("b"); 
a.push("c"); 

var b = Object.create(trackQueue.factory()); 
b.push("d"); 
b.push("e"); 
b.push("f"); 

a.work(); 
b.work(); 

E un jsfiddle

http://jsfiddle.net/dsjbirch/Wj6cp/10/

Sarebbe init essere un/nome appropriato più idiomatico per il metodo factory?

È pazzesco?

Essere gentile - javascript non è la mia lingua madre.

+2

Perché non vuoi usare 'new'? –

+1

Douglas crockford. – bluekeys

+2

Questo è un peccato. –

risposta

2

Sì, un metodo init sul prototipo potrebbe essere un nome più appropriato:

var proto = { 
    init: function(args) { 
     // setting up private-scoped vars, 
     var example = args; 
     // privileged methods 
     this.accessPrivate = function(){ return example; }; 
     // and other stuff 
     this.public = 5; 
    }, 
    prop: "defaultvalue", 
    ... 
} 

var instance = Object.create(proto); 
instance.init(); 

Tuttavia, non c'è assolutamente alcuna ragione per non utilizzare il costruttore classica con la nuova parola chiave, che combina elegantemente l'Object.create e init chiamata.

E si noti che si sta utilizzando Object.create con assolutamente inutile. Il modello di fabbrica (perfettamente valido applicato) restituisce buoni oggetti. Non è necessario creare nuovi oggetti per ognuno di essi che ereditano da essi. Basta fare:

var instance = trackQueue.factory(); 

Se vi piace il suono del nome del metodo "creare", è possibile utilizzare un nome più idiomatico per la fabbrica:

trackQueueFactory.create = function(args) {...}; 

EDIT: La tua idea di combinare il modello di fabbrica con l'ereditarietà del prototipo non è così sbagliato. Tuttavia, l'oggetto proto da cui ereditano tutti gli oggetti fabbricati deve essere statico, invece di creane uno nuovo su ciascuna chiamata.Il vostro codice potrebbe essere simile a questo:

var factory = { 
    proto: { 
     ... 
    }, 
    create: function(args) { 
     var product = Object.create(this.proto); 
     // set up private vars scoped to the create function 
     // privileged methods 
     product.doSomethingSpecial = function(){ ... }; 
     // and other stuff 
    } 
}; 

var a = factory.create(...); 
+0

Come si installano le scope private scope nella funzione init nell'esempio? – bluekeys

+0

Proprio come al solito: usa la parola chiave var o le dichiarazioni di funzione, e saranno portate alla funzione init. – Bergi

2

Credo che questo sia un modo chiaro per raggiungere i vostri requisiti:

var personFactory = function(id, name, age){ 
    var _id = id; 
    var _name = name; 
    var _age = age; 

    var personPrototype = { 
     getId: function(){ 
      return _id; 
     }, 
     setId: function(id){ 
      _id = id; 
     }, 
     getName: function(){ 
      return _name; 
     }, 
     setName: function(name){ 
      _name = name; 
     }, 
     getAge: function(){ 
      return _age; 
     }, 
     setAge: function(age){ 
      _age = age; 
     }, 
     work: function(){ 
      document.write(this.toString()); 
     }, 
     toString: function(){ 
      return "Id: " + _id + " - Name: " + _name + " - Age: " + _age; 
     } 
    }; 

    return Object.create(personPrototype); 
}; 

Usage:

var renato = personFactory(1, "Renato Gama", 25); 
console.log(renato.getName()); //logs "Renato Gama" 
renato.setName("Renato Mendonça da Gama"); 
console.log(renato.getName()); //logs "Renato Mendonça da Gama" 

Se non sbaglio questo è uno il MODULE PATTERN utilizza. Fare riferimento a this post per una spiegazione più accurata. This è anche un buon post sull'argomento.

+0

No, ti sbagli. Hai commesso lo stesso errore dell'OP: non è assolutamente necessario utilizzare Object.create su oggetti con scope privata. – Bergi

+0

Non riesco a capire il tuo punto, puoi chiarire un po '? Non riesco a capire perché è considerato un errore. Considero anche il tuo secondo blocco di codice simile a quello che ho scritto, differendo sul fatto che il tuo prototipo è un membro pubblico della fabbrica. Sono d'accordo con il tuo approccio se il tuo oggetto factory avesse più funzioni pubbliche ma create(). – renatoargh

+0

Perché non si restituisce direttamente l'oggetto letterale ("personPrototype")? A che cosa serve Object.create nel tuo codice? – Bergi

Problemi correlati