2017-05-31 45 views
0

我想创建一个产生函数构造函数作为产品的工厂。工厂拥有向产品原型添加方法的方法。实例化的产品拥有访问产品doc字段的这些功能。将方法添加到原型的范围困难

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" 

这种方法能正常工作,其只需要getter/setter方法DOC领域。但我需要更复杂的领域存取就像这个:

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

可悲的是我不能想出一个办法来定义createdeleteById功能并且具有其this关键字势必obj。我尝试添加原型方法的对象,但是这就是我无法弄清楚,如何让我的范围右:

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

(如何)是否有可能有createdeleteById函数将它们的this关键字绑定到我的obj实例?

回答

1

您只需使用bind即可将this范围绑定到您的函数上。如果我理解你想要什么this表示,这只是意味着标记.bind(this.Product);到你的函数结束:

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

但是,我认为这完全可以解决你的问题 - 当你调用addUserField没有的Product又一个实例为你绑定。所以你在上面得到的是this引用的Product的定义,而不是你的实例doc。为此你需要重构你的代码。

这里是一个改变你的工厂实际创建的Product的情况下,不太一样的你的解决方案,但希望满足同样的要求

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

关于“但是,我认为这完全解决了你的问题“:是的,我目前正在测试那个,因为我发现了同样的问题: https://jsfiddle.net/5n5pachh/4/ 编辑:试着绑定'th “产品原型”也没有意义。 – FabianTe

+0

@Fabi是的,我们已经遵循了相同的试验 - 我目前正在研究一个完全一样的重构,但工作:) – Jamiec

+0

@Fabi你需要这种创建类的模式,然后'新的'它呢?或者你的工厂是否有'createProduct(doc)'方法?也就是'var prod = new Factory()。addUserField(...)。createProduct(myDoc)' – Jamiec