我想创建一个生产函数构造函数的工厂作为产品。工厂拥有为产品原型添加方法的方法。实例化产品包含用于访问产品文档字段的这些功能。
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");
遗憾的是,我无法找到定义create
和deleteById
函数并将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;
}
(如何)是否可以让create
和deleteById
函数将this
关键字绑定到我的obj
实例?
答案 0 :(得分: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){
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();