2017-05-31 4 views
0

Ich möchte eine Factory erstellen, die einen Funktionskonstruktor als Produkt erzeugt. Die Factory enthält Methoden zum Hinzufügen von Methoden zum Prototyp des Produkts. Das instanziierte Produkt enthält diese Funktionen für den Zugriff auf das Dokumentfeld "Produkte".Probleme beim Hinzufügen von Methoden zum Prototyp

https://jsfiddle.net/84fzwvj7/2/

function Factory() { 
    this.Product = function(doc = {}) { 
     this.doc = doc; 
    } 
} 

Factory.prototype.addDocField = function(name) { 
    this.Product.prototype["set" + name] = function(value) { 
     this.doc[name] = value; 
    } 
    this.Product.prototype["get" + name] = function() { 
     return this.doc[name]; 
    } 
    return this; 
} 

var MyClass = new Factory().addDocField("Test").Product; 
var obj = new MyClass(); 
console.dir(obj.doc.Test);   // undefined 
obj.setTest("Lorem Ipsum"); 
console.dir(obj.doc.Test);   // "Lorem Ipsum" 

Diese Methode für doc Felder gut funktioniert, die nur Getter/Setter müssen. Aber ich brauche mehr komplexes Feld Accessoren wie in dieser:

// ... Object was created before with an array like field 
obj.users.create(login); 
obj.users.deleteById("46891"); 

Leider kann ich nicht einen Weg finden, die create und deleteById Funktionen zu definieren, die ihr this Schlüsselwort obj gebunden. Ich versuchte, die Prototyp-Methoden auf ein Objekt hinzugefügt, aber das ist, wo ich kann nicht herausfinden, wie meinen Umfang erhalten rechts:

https://jsfiddle.net/5n5pachh/3/

Factory.prototype.addUserField = function(name) { 
    this.Product.prototype[name] = {}; 

    // Using a classic function does not work because ... 
    this.Product.prototype[name].create = function(login) { 
     console.dir(this); // ... 'this' is bound to this.Product.prototype[name] 
    } 

    // Using an arrow function does not work because ... 
    this.Product.prototype[name].create = function(login) { 
     console.dir(this); // ... 'this' is bound to Factory.prototype.addUserField 
    } 

    // None of the above functions work how I want them to, because they can't 
    // access the products doc field (i.e.: this.doc) 

    return this; 
} 

(Wie) Ist es möglich, die create und deleteById haben Funktionen haben ihre this Schlüsselwort an meine obj Instanz gebunden?

Antwort

1

Sie müssen einfach bind verwenden, um den Bereich this an Ihre Funktion zu binden. Wenn ich verstehe, was Sie wollen this vertreten bedeutet dies nur .bind(this.Product); auf das Ende Ihrer Funktionen Tagging:

this.Product.prototype[name].create = function(login) { 
    console.dir(this); 
}.bind(this.Product); 

Aber ich glaube nicht, dass dies völlig Ihr Problem löst - wenn Sie addUserField nennen es noch nicht eine Instanz von Product ist damit du dich daran binden kannst. Also, was Sie mit dem oben erhalten, ist this Bezug auf die Definition von Product, nicht Ihre Instanz mit einer doc. Dafür müssen Sie Ihren Code umgestalten.

Hier ist eine Lösung, die Ihre Fabrik ändert sich die Instanz von Product, nicht ganz das gleiche wie Sie tatsächlich zu schaffen, aber hoffentlich erfüllt die gleiche Anforderung

function Factory() { 
 
     
 
    this.createProduct = function(doc){ 
 
     var product = {doc:doc}; 
 
     userFields.forEach(function(uf){ 
 
      product[uf.name] = {}; 
 
      product[uf.name].create = uf.create.bind(product) ; 
 
     }) 
 
     return product; 
 
    } 
 
    
 
    var userFields = []; 
 
    this.addUserField = function(name){ 
 
    \t userFields.push({ 
 
      name: name, 
 
      create: function(login){ 
 
       console.dir(this.doc); 
 
      } 
 
     }) ; 
 
     return this; 
 
    } 
 
} 
 

 

 

 
// Use case 
 
var obj = new Factory().addUserField("users").createProduct({foo:"bar"}); 
 
console.log(obj.doc) 
 
obj.users.create();

+0

In Bezug auf „Aber ich glaube nicht, das löst das Problem ganz aus ": Ja, ich teste das auch gerade, da ich das gleiche Problem gefunden habe: https://jsfiddle.net/5n5pachh/4/ Edit: Versuchsbindung' th Ist.Produkt.Prototyp "hat auch keinen Sinn ergeben. – FabianTe

+0

@Fabi yep, wir haben die gleichen Versuche verfolgt - ich arbeite gerade an einem Refactor, der genau das gleiche funktioniert aber funktioniert :) – Jamiec

+0

@Fabi brauchst du dieses Muster um die Klasse zu erstellen, und dann 'neu' es? Oder könnte Ihre Fabrik eine 'createProduct (doc)' Methode haben? dh 'var prod = new Factory(). addUserField (...). createProduct (myDoc)' – Jamiec

Verwandte Themen