2011-05-05 11 views
6

方案1 - 一切正常:模式需要:创建新的对象,它返回一个executeable功能,并继承了原型

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 

现在我想它甚至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 

新AwesomeObject应该返回一个可执行的函数本身,所以我可以说'真棒();'

但我希望它也继承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

我认为只是从原型复制你需要的功能。你不需要使用apply();只是做self.doStuff = prototype.doStuff – Joel 2011-05-05 10:27:28

回答

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

Live Example

这个想法是,你把你的功能和你的对象分成两件事情。您的对象存在于您的函数的本地范围中,并且该函数可以使用该对象。

该对象本身完全通过原型继承。

关键是将对象的所有属性/方法转发到函数上。

这是最干净的解决方案。

+0

其他答案也是正确的。这似乎是最干净的模式(它像承诺的那样工作)。多谢。 – 2011-05-05 13:53:05

+1

请注意,此解决方案不会*返回一个继承自您的自定义原型的对象,但它确实会返回一个将某些属性混入其中的'Function'对象。 – Bergi 2014-01-08 22:16:21

1

我不认为有这样做的好方法。我会重新设计你的程序来避免它。

var PrototypeToBeInherited = {'inheritedProperty': 'inheritedPropertyValue'}; 

f = function() { 
    return "result"; 
}; 
f.__proto__ = PrototypeToBeInherited; 

f() 
=> "result"; 
f.inheritedProperty 
=> "inheritedPropertyValue" 

您的需求,它必须以“新”创建:

然而,这里是一个平台相关溶液(使用非标准__proto__财产上的V8作品) ,只是把它包装在功能中:

F = function() { 
    return f; 
} 
var instance = new F(); 
+0

我会再次指出'.__ proto__'应该避免由于平台依赖和改变对象的内部原型动态导致噩梦代码。 – Raynos 2011-05-05 11:48:20

+0

thx很多,它帮助ged摆脱了我在想法 – 2011-05-05 13:52:29

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时无法区分构造函数或常规函数。

对象o上解析属性p时的过程大致如下:

  • 检查是否po
  • 检查是否po.__proto__定义(的__proto__使用是非限定标准但广泛实施,除了jscript上次我检查,它现在已被弃用在SpiderMonkey中)
  • 检查p是否为de被罚上o.constructor.prototype
  • 检查是否po.constructor.prototype.prototype
  • 定义等

所以一个解决办法是简单地设置o.__proto__ = AwesomeClass.prototype。将__proto__想象为对象与其原型之间的隐藏中介对象。每个实例都会收到其自己的唯一__proto__对象。但是,像我说的那样,这已经被弃用和非标准化了。

我们也可以设置Function.prototype中的值,但会覆盖其他函数属性并影响所有函数实例。我们不希望这样。

那剩下什么了?结果并不多。没有办法设置对象的完整原型,同时保留它的继承原型。您需要遍历原型并复制所有属性。幸运的是,这将允许instanceof在处理构造函数链时的预期行为,以及允许继承/正确覆盖属性。

问题是,没有内置的方法来将对象的属性复制到另一个对象中,并且没有标准的方法来更改对象的原型链专用(__proto__)。所以使用__proto__,或者遍历原型。

+0

thx在__proto__中的话语结。我现在知道proto了,现在我会尝试不用用户__proto__ – 2011-05-05 13:51:31