场景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;
}
但我认为必须有更好的方法,更好的模式,它是什么?
这个问题让我发疯,帮助真的很感激。一般来说:如何创建一个
的函数对象
有办法吗?
THX 弗朗兹
答案 0 :(得分:8)
一个非常简单的模式是工厂。
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();
我们的想法是将您的功能和对象分成两部分。您的对象存在于函数的本地范围内,函数可以使用该对象。
对象本身完全通过原型继承。
关键是将对象的所有属性/方法转发到函数上。
这是最干净的解决方案。
答案 1 :(得分:2)
当一个属性被解析时,你可能知道原型链的遍历。
但是,如果您有一个对象awesome
并尝试评估awesome.doStuff
,则永远不会查询awesome.prototype
该属性。您可以在示例"doStuff" in awesome => false
但"doStuff" in awesome.prototype => true
中对此进行验证。
所以你所做的不是改变awesome
的隐式属性,而是改变它的原型,这意味着通过执行new awesome
创建的任何对象都将拥有该属性。验证:"doStuff" in new awesome() => true
。这是有道理的,因为在使用f/awesome
时无法区分构造函数或常规函数。
解析对象p
上的属性o
时的过程大致如下:
p
o
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
在使用构造函数链时按预期运行,并允许正确地继承/覆盖属性。
问题实际上是没有内置的方法将对象的属性复制到另一个对象中,并且没有标准方法来更改对象的原型链ad-hoc(__proto__
)。
所以使用__proto__
,或者遍历原型。
答案 2 :(得分:1)
我认为没有好方法可以做到这一点。我会重新设计你的程序以避免它。
但是,这是错误,平台相关解决方案(适用于使用非标准__proto__
属性的V8):
var PrototypeToBeInherited = {'inheritedProperty': 'inheritedPropertyValue'};
f = function() {
return "result";
};
f.__proto__ = PrototypeToBeInherited;
f()
=> "result";
f.inheritedProperty
=> "inheritedPropertyValue"
对于您必须使用“new”创建的要求,只需将其包装在函数中:
F = function() {
return f;
}
var instance = new F();