7

EDIT: Ich habe es am Ende aus Bergis Antwort herausgefunden.Wie erstellt man ein Objekt mit privaten Mitgliedern mit Object.create() anstelle von

Danke 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: Es scheint die Antworten auf meine Frage sind an einer Tangente aus. Ich bin wirklich nicht an einer Fabrik interessiert und möchte sie lieber nicht benutzen. Meine Frage betrifft den privaten Staat. Aus Bergis Antworten und Kommentaren denke ich, dass ich etwas zusammenziehen kann.

fortgesetzt ...

EDIT: Bergi hat damit begonnen, die Frage unten, zu beantworten, aber den wichtigsten Teil ausgelassen - den privaten Zustand.

Ich hatte Zeit, um über die Idee mehr nachzudenken, aber bin immer noch nicht in der Lage, privaten Zustand mit Object.create() ohne irgendeine Art von Fabrik zu erreichen. Aber ich möchte mich irren, und Bergi hat auf eine Lösung angespielt ... Fühlen Sie sich frei, Bergis Antwort als Ausgangspunkt zu nehmen.

ORIGINAL: Meine Suche zu vermeiden new in Javascript hat mich zu einem besonderen Ort geführt. Ich möchte private Objekt-Mitglieder, aber ich möchte nicht aufgeben Object.create().

Hier ist der Code.

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(); 

Und ein jsfiddle

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

Would init sein eine idiomatische/geeigneten Namen für die factory Methode?

Ist das verrückt?

Sei nett - Javascript ist nicht meine Muttersprache.

+2

Warum möchten Sie nicht 'neu' verwenden? –

+1

Douglas Crockford. – bluekeys

+2

Das ist bedauerlich. –

Antwort

2

Ja, eine init-Methode auf dem Prototyp möglicherweise ein geeignetere Name:

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(); 

Allerdings gibt es absolut keinen Grund, nicht die klassische Konstruktor mit dem neuen Schlüsselwort zu verwenden, die elegant die Object.create kombiniert und init Anruf.

Und beachten Sie, dass Sie Object.create mit absolut keinen Nutzen verwenden. Ihr Werksmuster (perfekt gültig angewendet) gibt gute Objekte zurück. Keine Notwendigkeit, neue Objekte für jede zu erstellen, die von ihnen erben. Just do:

var instance = trackQueue.factory(); 

Wenn Sie den Klang des Methodennamen "create" mögen, haben Sie vielleicht eine mehr idiomatische Namen für die Fabrik verwenden:

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

EDIT: Ihre Idee zu verbinden Das Fabrikmuster mit Prototypvererbung ist nicht so falsch. Das Proto-Objekt, aus dem alle gefertigten Objekte erben, muss jedoch statisch sein, anstatt zu erstellen, um bei jedem Aufruf einen neuen zu erstellen.Der Code könnte wie folgt aussehen:

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

Wie konfiguriere ich private scoped vars in der init-Funktion in Ihrem Beispiel? – bluekeys

+0

Ganz normal: Verwenden Sie die var-Schlüsselwort- oder Funktionsdeklarationen, und sie werden auf die init-Funktion beschränkt. – Bergi

2

Ich denke, dies ist ein klarer Weg, um Ihre Anforderungen zu erreichen:

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); 
}; 

Verbrauch:

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" 

Wenn ich nicht falsch bin dies ist ein die MODULMUSTER Verwendungen. Eine genauere Erklärung finden Sie unter this post. This ist auch ein guter Beitrag über das Thema.

+0

Nein, Sie liegen falsch. Sie haben den gleichen Fehler wie das OP gemacht: Es ist absolut nicht notwendig, Object.create für private-scope-faktorisierte Objekte zu verwenden. – Bergi

+0

Ich kann Ihren Standpunkt nicht verstehen, können Sie ein wenig klären? Kann nicht sehen, warum es als ein Fehler angesehen wird. Ich denke sogar, dass Ihr zweiter Codeblock dem ähnlich ist, den ich geschrieben habe, und unterscheidet sich von der Tatsache, dass Ihr Prototyp ein öffentliches Mitglied der Fabrik ist. Ich stimme Ihrer Herangehensweise zu, wenn Ihr Fabrikobjekt mehr öffentliche Funktionen hätte als die create(). – renatoargh

+0

Warum geben Sie das Objektliteral ("personPrototype") nicht direkt zurück? Welchen Nutzen hat Object.create in Ihrem Code? – Bergi

Verwandte Themen