添加原型方法时的范围困难(Scope difficulties when adding methods to prototype)

编程入门 行业动态 更新时间:2024-10-26 04:29:34
添加原型方法时的范围困难(Scope difficulties when adding methods to prototype)

我想创建一个生产函数构造函数的工厂作为产品。 工厂拥有为产品原型添加方法的方法。 实例化产品包含用于访问产品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");

遗憾的是,我无法找到一种方法来定义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实例?

I'd like to create a factory that produces a function constructor as a product. The factory holds methods for adding methods to the products prototype. The instantiated product holds these functions for accessing the products doc field.

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"

This method works fine for doc fields which need only getters / setters. But I need more complex field accessors like in this:

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

Sadly I can't figure out a way to define the create and deleteById functions and having their this keyword bound to obj. I tried adding the prototype methods to an object but that's where I can't figure out, how to get my scope right:

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

(How) Is it possible to have the create and deleteById functions have their this keyword bound to my obj instance?

最满意答案

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

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

但我不认为这完全解决了你的问题 - 当你调用addUserField ,还没有一个Product实例供你绑定。 所以你对上面的内容是引用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(); 
  
 

You simply need use bind to bind the this scope onto your function. If I understand what you want this to represent this just means tagging .bind(this.Product); onto the end of your functions:

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

But I dont think this entirely solves your problem - when you call addUserField there is not yet an instance of Product for you to bind to. So what you get with the above is this referencing the definition of Product, not your instance with a doc. For that you will need to refactor your code.

Here is a solution which changes your factory to actually create the instance of Product, not quite the same as yours but hopefully fulfils the same requirement

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

更多推荐

本文发布于:2023-08-06 21:44:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1457584.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:原型   困难   方法   Scope   prototype

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!