2010-10-21 119 views
0

我試圖在JavaScript中實現某種類的層次結構。 I 認爲我理解了原型鏈,但我仍然必須理清構造函數鏈的 。繼大衛·弗拉納根的Definitive Guide, 我寫JavaScript中的鏈接構造函數

function DerivedClass() 
{ 
    BaseClass.apply(this, arguments); // chain constructors 
    // do some initializations specific to DerivedClass... 
} 

var foo = new DerivedClass(); 

其中BaseClass()是用C寫的我的本地函數++(我 使用QtScript)。我的問題是,那麼,BaseClass()被稱爲 作爲一個函數,而不是一個構造函數。

我可以編碼BaseClass()始終表現爲構造函數,但它調用 。但恐怕我的一些用戶一天一個可能會忘記new 和只寫

var bar = BaseClass(); 

在這種情況下,我想BaseClass()做一些更 不是初始化的全局對象明智的。例如:

if (!context->isCalledAsConstructor()) fail_gracefully(); 

但是然後構造函數鏈失敗!

有沒有辦法鏈接構造函數並讓BaseClass() 實際上被稱爲構造函數?或者我應該教育我的用戶 永遠不會忘記new?現在我很想通過更換上述 測試:

if (context->thisObject().strictlyEquals(engine->globalObject())) 
    fail_gracefully(); 

,但我不知道是否有處理這種更清潔的方式。

謝謝!

回答

0

回答自己...

我想到了我的問題過夜......我想我發現了一個有點 更令人滿意的解決方案:表現爲一個構造函數,如果this是卡萊的 實例。這個測試比檢查 更嚴格一點,不管它是不是全局對象,但它仍然允許構造函數 鏈接,只要原型已被正確鏈接。

這裏是我的家鄉構造函數的第一行(SerialPort是我 基類,圍繞QSerialDevice建):

/* 
* Should we behave as a constructor? 
* 
* We could use context->isCalledAsConstructor() to decide. However, 
* we may want to subclass SerialPort in JavaScript and chain the 
* constructors: 
* 
*  function DerivedClass() 
*  { 
*   SerialPort.apply(this, arguments); 
*   // do some more initializations... 
*  } 
* 
* This would fail if we decided on the basis of 
* context->isCalledAsConstructor(). The test below is somewhat less 
* strict. It allows constructor chaining provided the prototypes 
* have been properly chained. 
*/ 
bool behave_as_constructor = 
    context->thisObject().instanceOf(context->callee()); 

關於這個有趣的是:不像isCalledAsConstructor(),這 測試也可以實現在JavaScript構造函數中!

0

你應該教育你的用戶永遠不會忘記new

JavaScript中的所有「構造函數」畢竟都是函數,因此您無法防止構造函數被調用爲函數。

這是不正確的JavaScript嘗試和創建一個新的對象,而不使用new。僅僅因爲沒有像Java那樣的「編譯時間警告」,並沒有改變它。

+0

嗯,從技術上講,我可以通過拋出一個異常來保護它們,或者忽略'this'並返回一個全新的對象(比如'Array()')。我的問題是,第一個選項干擾構造函數鏈,而第二個選項與原型鏈不兼容。 – 2010-10-21 12:54:40