2010-06-24 93 views
9

我遇到了以下問題,它真的讓我難住了:調用成員函數

function SystemList(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 

當我嘗試和運行它,我得到以下錯誤:未捕獲TypeError:Object#在構造函數中沒有方法'refreshData'。

任何人都有一個想法,爲什麼這是失敗?在我看來,它看起來應該起作用。

編輯:

function UserMiniProfile(UID) 
{ 
    this.UID = UID; 
    this.systemList = new SystemList(this.UID); 
    this.htmlID = 'user-'+this.UID+'-profile'; 
} 
+0

添加了一個如何創建obj的示例。 – nazbot 2010-06-24 05:04:11

+1

確定在擴充其原型後使用'SystemList'構造函數*嗎? – CMS 2010-06-24 05:09:45

+0

適用於我:http://jsbin.com/ebasa/edit – nickf 2010-06-24 05:10:16

回答

13

我想你可能運行到這個問題我如何創建一個實例

例如何以及何時函數聲明與逐步代碼(規範所稱的聲明代碼)發生。因爲你要添加的setName函數原型之前調用構造函數

var obj = new Thingy("Fred"); 

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

...:

這樣的代碼將在你所描述的方式失敗,例如。請注意,在聲明之前調用構造函數就好了,這是因爲構造函數正在使用一個函數,該函數通過聲明代碼設置了以後的,這有一個問題。 JavaScript解釋器嘗試處理該代碼的順序爲:

  1. 創建函數Thingy並使其可用於範圍。執行var obj = ....一行,調用構造函數。
  2. 執行構造函數的代碼(在這種情況下拋出異常,因爲沒有this.setName函數)。
  3. 執行Thingy.prototype.setName = ...一行。 (如果在最後一步沒有拋出異常,那就是)

這些步驟發生在每個腳本塊(首先完成函數聲明,然後按順序執行語句代碼),並且即使上面的例子相當明顯,當你開始把來自不同地點的棋子拼湊在一起時,你可以創造出這種情況不那麼明顯。

解決辦法,很明顯,是要確保你已經設置了setName屬性之前你不是構造對象:

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

var obj = new Thingy("Fred"); 

...又一次,上面是相當明顯的,但有可能在現實世界中創造這些情況而不那麼明顯。

我懷疑這是你的情況發生了什麼。很容易證明:使用像Firefox上的Firebug,VS.Net或IE的腳本調試器,Chrome的DevTools等調試器。,在SystemList.prototype.refreshData = ...行上放置一個斷點,在你正在執行new SystemList(...)的行上放置一個斷點並查看哪一行首先執行。

下面是一些演示問題的小提琴:This one失敗的構造函數,this one成功。

+0

對不起,延遲,是的,這是問題。我移動了東西,現在它可以工作。 – nazbot 2010-06-28 18:51:54

+0

@nazbot:啊,很好,很高興就是這樣! – 2010-06-28 18:59:03

0

您需要首先分配類:

SystemList = function(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 
+0

真的嗎?我從來沒有見過這種指定js類的方式。 – nazbot 2010-06-24 04:42:13

+2

不,將其從'function SystemList(UID)'更改爲'SystemList = function(UID)'與它無關。它所做的只是將其從命名函數更改爲匿名函數。 – 2010-06-24 04:45:42

+3

(引用自己)*「它所做的一切就是將其從命名函數更改爲匿名函數。」*實際上,這不是它的全部*。它也將它從函數*聲明*更改爲函數*表達式*,這將在稍後發生。如果我對OP的代碼做了正確的描述,這種改變的可能結果是,不是構造函數失敗,對構造函數的*調用將會失敗,因爲'SystemList'是未定義的。這兩種方式都不能解決問題,但我之前的陳述並不完整,所以我認爲我應該舉報。 – 2010-06-24 05:30:53