Javascript 所需模式:创建新对象,该对象返回可执行函数并从原型继承
场景1-一切正常:Javascript 所需模式:创建新对象,该对象返回可执行函数并从原型继承,javascript,node.js,Javascript,Node.js,场景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 awesom
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
新的awesome对象本身应该返回一个可执行函数,这样我就可以说“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;
}
但我认为一定有更好的方式,更好的模式,这是什么
这个问题让我发疯,我非常感谢你的帮助
概述:如何创建一个函数对象
- 可以使用新的
- 返回可以执行的函数对象
- 继承给定原型的所有属性和方法
?
有办法吗
thx
弗兰兹我认为没有好办法。我会重新设计你的程序来避免它
但是,这里有一个糟糕的,依赖于平台的解决方案(在V8上使用非标准的\uuuu proto\uuu
属性):
对于必须使用“new”创建的需求,只需将其包装在函数中:
F = function() {
return f;
}
var instance = new F();
当一个属性被解析时,原型链被遍历,这一点您可能知道。
但是,如果您有一个对象awesome
,并尝试评估awesome.doStuff
,那么将永远不会查询该属性的awesome.prototype
。您可以在示例中验证这一点,awome=>false中的“doStuff”,而awome.prototype=>true中的“doStuff”
因此,您所做的不是更改awesome
的隐式属性,而是更改其原型,这意味着通过执行newawesome
创建的任何对象都将具有该属性。验证:新awesome()中的“doStuff=>true
。这很有意义,因为在使用f/awesome
时,无法区分构造函数和常规函数
在对象o
上解析属性p
的过程大致如下:
- 检查是否在
o
- 检查
p
是否定义在o.\uuuuu proto\uuuuuuu
(使用\uuuuuuuu proto\uuuuuuuu
是非标准的,但得到了广泛的实现,除了我上次检查的jscript之外,它现在已在SpiderMonkey中被弃用)
- 检查是否在
o.constructor.prototype上定义了p
- 检查
o.constructor.prototype.prototype上是否定义了p
- 等
因此,一个解决方案是简单地设置o.。\uuuuu proto\uuuuu=AwesomeClass.prototype
。将\uuuu proto\uuu
视为对象与其原型之间隐藏的中间对象。每个实例都接收自己唯一的\uuuuuuuuuuuuu
对象。但正如我所说,这是不推荐的和非标准的
我们还可以在Function.prototype
中设置值,但这将覆盖其他函数属性并影响所有函数实例。我们不想那样
剩下什么?结果不多。在保留继承的原型的同时,无法设置对象的完整原型。您需要遍历原型并复制所有属性。幸运的是,这将允许instanceof
在使用构造函数链时按预期运行,并允许正确继承/重写属性
问题是,实际上没有内置的方法将对象的属性复制到另一个对象中,也没有标准的方法来临时更改对象的原型链(\uuuuuu proto\uuu
)
因此,请使用\uuuuu proto\uuuuu
,或者迭代原型 一个非常简单的模式是工厂
var AwesomeObject = (function() {
var AwesomeObject = function() {
this.whatstuff = 'really awesome';
};
AwesomeObject.prototype.doStuff = function() {
console.log('i did ' + this.whatstuff + ' stuff');
return this;
};
return function() {
var o = new AwesomeObject();
var f = function() { console.log("I am awesome"); };
for (var k in o) {
f[k] = o[k];
}
return f;
};
})();
var foo = AwesomeObject();
foo();
foo.doStuff();
这个想法是你把你的功能和你的对象分成两部分。对象存在于函数的本地范围内,函数可以使用该对象
对象本身完全通过原型继承
关键是将对象的所有属性/方法转发到函数上
这是最干净的解决方案。我认为只需从原型复制您需要的功能即可。您不需要使用apply();doStuff=prototype。doStuff支持。\uuuu proto\uuuu
应该避免,因为平台依赖,动态更改对象的内部原型会导致噩梦代码。thx很多,它帮助ged摆脱了我在proto中的讨论中我在思想上的结。我现在知道了proto,现在我会尽量避免使用proto,因为其他答案也是正确的。这似乎是最干净的模式(它的工作原理与承诺的一样)。thx很多。请注意,此解决方案不会返回从自定义原型继承的对象,而是返回一个混合了某些属性的函数对象。
var AwesomeObject = (function() {
var AwesomeObject = function() {
this.whatstuff = 'really awesome';
};
AwesomeObject.prototype.doStuff = function() {
console.log('i did ' + this.whatstuff + ' stuff');
return this;
};
return function() {
var o = new AwesomeObject();
var f = function() { console.log("I am awesome"); };
for (var k in o) {
f[k] = o[k];
}
return f;
};
})();
var foo = AwesomeObject();
foo();
foo.doStuff();