2011-05-05 42 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