所需模式:创建返回可执行函数并继承自原型的新对象
场景 1 - 一切正常:
var AwesomeObject = function()
{
var self = this;
self.whatstuff = 'really awesome';
}
AwesomeObject.prototype.doStuff = function()
{
var self = this;
console.log('i did '+self.whatstuff+' stuff');
return self;
}
var awesome = new AwesomeObject(); //returns a new AwesomeObject
awesome.doStuff(); // prints 'i did really awesome stuff' on the console
现在我希望它更棒:
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
return self;
}
AwesomeObject.prototype.doStuff = function()
{
var self = this;
console.log('i did '+self.whatstuff+' stuff');
return self;
}
var awesome = new AwesomeObject(); //returns the interal f object
awesome(); // prints 'i am awesome'
awesome.doStuff(); // throws an error
新的 AwesomeObject 应该返回一个可执行函数本身,这样我就可以说“awesome();”
但我希望它也继承 AwesomeObject.prototype
。
添加 self.prototype = AwesomeObject.prototype; 没有帮助。
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
self.prototype = AwesomeObject.prototype;
return self;
}
好吧,我可以将 AwesomeObject.prototype
函数一个接一个地复制到 f
的范围内,
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
self.doStuff = function() { AwesomeObject.prototype.doStuff.apply(self,arguments); }
return self;
}
但我认为必须有一种更好的方法,更好的模式,什么是它?
这个问题让我发疯,非常感谢您的帮助。
一般来说:如何创建一个
- 可以用new创建的
- 函数对象返回一个可以执行的函数对象
- 继承给定原型的所有属性和方法
?
有办法吗?
谢谢 弗朗兹
Scenario 1 - everything works:
var AwesomeObject = function()
{
var self = this;
self.whatstuff = 'really awesome';
}
AwesomeObject.prototype.doStuff = function()
{
var self = this;
console.log('i did '+self.whatstuff+' stuff');
return self;
}
var awesome = new AwesomeObject(); //returns a new AwesomeObject
awesome.doStuff(); // prints 'i did really awesome stuff' on the console
Now i want it even awesomer:
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
return self;
}
AwesomeObject.prototype.doStuff = function()
{
var self = this;
console.log('i did '+self.whatstuff+' stuff');
return self;
}
var awesome = new AwesomeObject(); //returns the interal f object
awesome(); // prints 'i am awesome'
awesome.doStuff(); // throws an error
new AwesomeObject should return an executable function itself, so that i can say 'awesome();'
but i want it to inherit the AwesomeObject.prototype
, too.
adding self.prototype = AwesomeObject.prototype;
does not help.
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
self.prototype = AwesomeObject.prototype;
return self;
}
ok i can copy the AwesomeObject.prototype
functions - one after the other - into the scope of f
var AwesomeObject = function()
{
var f = function() { console.log('i am awesome'); }
var self = f;
self.whatstuff = 'really awesome';
self.doStuff = function() { AwesomeObject.prototype.doStuff.apply(self,arguments); }
return self;
}
but i think there must be a better way, a better pattern, what is it?
this issue drives me crazy, help would be really appreciated.
in general: how to create a function object that
- can be created with new
- returns a function object that can be executed
- inherits all properties and methods of a given prototype
?
is there a way?
thx
Franz
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一个非常简单的模式就是工厂。
实例。
这个想法是将函数和对象分成两部分。您的对象存在于函数的本地范围内,并且该函数可以使用该对象。
对象本身完全通过原型继承。
关键是将对象的所有属性/方法转发到函数上。
这是最干净的解决方案。
A very simple pattern is a factory.
Live Example.
The idea is that you seperate your function and your object into two things. Your object exists in the local scope of your function and the function can use the object.
The object itself inherits completely through the prototype.
The key is do forward all properties/methods of the object onto the function.
This is the cleanest solution.
正如您可能知道的那样,当解析属性时,将遍历原型链。
但是,如果您有一个对象
awesome
并尝试评估awesome.doStuff
,则永远不会查询awesome.prototype
的属性。您可以在示例中验证这一点,"doStuff" in Awesome =>; false
但是awesome.prototype => 中的“doStuff”正确。
因此,您所做的并不是更改
awesome
的隐式属性,而是更改其原型,这意味着通过执行new Awesome
创建的任何对象都将具有该属性。验证:new Awesome() => 中的“doStuff”正确。这是有道理的,因为使用
f/awesome
时无法区分构造函数或常规函数。解析对象
o
上的属性p
的过程大致如下:o
上是否定义了p
>p
是否在o.__proto__
上定义(__proto__
的使用是非标准的,但广泛实现,除了我上次检查的 jscript现在已在 SpiderMonkey 中弃用)p
是否在o.constructor.prototype
上定义p
是否在上定义o.constructor.prototype.prototype
因此,一种解决方案是简单地设置 o.__proto__ = AwesomeClass.prototype 。将 __proto__ 视为对象与其原型之间的隐藏中间对象。每个实例都会接收自己唯一的 __proto__ 对象。但正如我所说,这已被弃用且非标准。
我们还可以在 Function.prototype 中设置值,但这会覆盖其他 Function 属性并影响所有 Function 实例。我们不希望这样。
那么还剩下什么呢?事实证明并不多。无法在保留对象继承原型的同时设置对象的完整原型。您将需要迭代原型并复制所有属性。幸运的是,这将允许
instanceof
在使用构造函数链时按预期运行,并允许正确继承/重写属性。问题实际上是没有内置方法可以将一个对象的属性复制到另一个对象中,并且没有标准方法可以临时更改对象的原型链(
__proto__
)。因此,请使用 __proto__ ,或迭代原型。
When a property is resolved the prototype chain is traversed as you probably know.
But if you have an object
awesome
and try to evaluateawesome.doStuff
, thenawesome.prototype
will never be queried for the property. You can verify this in your example,"doStuff" in awesome => false
but"doStuff" in awesome.prototype => true
.So what you're doing is not changing the implicit properties of
awesome
, you are changing its prototype, meaning any objects created by doingnew awesome
will have that property. Verification:"doStuff" in new awesome() => true
. And this makes sense, since there is no way to distinguish between a constructor or a regular function when usingf/awesome
.The procedure when resolving a property
p
on an objecto
is roughly as follows:p
is defined ono
p
is defined ono.__proto__
(usage of__proto__
is non-standard but widely implemented, except for jscript last time i checked and it has now been deprecated in SpiderMonkey)p
is defined ono.constructor.prototype
p
is defined ono.constructor.prototype.prototype
So one solution would be to simply set
o.__proto__ = AwesomeClass.prototype
. Think of__proto__
as a hidden intermediary object between an object and its prototype. Each instance receives its own unique__proto__
object. But this is deprecated and non-standard like I said.We could also set the values in
Function.prototype
but that would override other Function properties and affect all Function instances. We don't want that.So what's left? Not much it turns out. There is no way to set the complete prototype of an object while retaining it's inherited prototype. You will need to iterate through your prototype and copy all properties. Fortunately this will allow
instanceof
to behave as expected when working with chains of constructors, as well as allowing inheritance/overriding of properties properly.The problem is really that there is no built-in way to copy the properties of an object into another one, and that there is no standard way to change an object's prototype chain ad-hoc (
__proto__
).So use
__proto__
, or iterate through the prototype.我认为没有一个好的方法可以做到这一点。我会重新设计你的程序来避免它。
然而,这是一个糟糕、依赖于平台的解决方案(使用非标准
__proto__
属性在V8上工作):根据您的要求,它必须使用“new”创建,只需将其包装在函数中:
I don't think there is a good way to do this. I would redesign your program to avoid it.
However, here is a bad, platform-dependent solution (works on V8 using non-standard
__proto__
property):For your requirement that it must be created with "new", just wrap it in function: