[英]JavaScript call parent function from child object
我是javascript的面向對象編程的新手。 並嘗試實現我們從其他編程語言中了解的基礎知識。
我有兩個班,一個家長和一個孩子。 父母有一些私人功能和一些公共功能。 Child將繼承父類。
我希望從子對象訪問父公共函數。 我想做什么:
function SuperClass {
//Constructor implementation of this class
//public functions
return {
parentPublicFunction: function() {
//Public function implementation
}
}
function privateFunction() {
//Private function implementation.
}
}
//Inheriting
childClass.prototype = Object.create(SuperClass.prototype);
childClass.prototype.constructor = childClass;
childClass.prototype.parent = SuperClass.prototype;
function childClass {
//Call to super constructor
this.parent.constructor.call(this, arguments);
//Public function for childClass.
return {
childPublicFunction: function() {
//function implementation
}
}
}
var childObj = new childClass();
childObj.parentPublicFunction();
我在運行時收到此錯誤:
未捕獲的TypeError:undefined不是函數
我做的是不正確的事嗎? 提前致謝!
JavaScript OOP不像Java或C#那樣工作,不要指望它,也不要嘗試制作它。 這樣做的唯一原因是誤解。 而不是試圖強制你的舊范式完全不同的語言,而是學習JavaScript OOP的工作原理。
JavaScript是面向對象的,但這並不意味着它有類。 至少不是大多數來自Java或類似語言的開發人員都會想到類。 它也沒有經典繼承。 但是,所有這些都可以“偽造”或模仿(這是你有效地嘗試做的)。 這樣做的問題是,來自Java或類似的開發人員看到類似於類和經典繼承的代碼,因此他們認為它是具有經典繼承的類,並期望它表現得如此,而它可能最終完全工作不同。
讓我們從你的SuperClass
函數開始(因為它就是它。它是一個函數,而不是一個類)。 首先,您的代碼甚至不是有效的語法,因為您的SuperClass
函數沒有括號。 正確的語法是function SuperClass() { ... }
。
其次,JavaScript使用原型來處理對象(而不是類)之間的繼承,如果你想做原型繼承(你的一些代碼建議你想要),你就不能從SuperClass
函數返回一個新的匿名對象。 請允許我說明一下這里發生了什么。
使用new
關鍵字調用SuperClass
函數(來自childClass
函數或來自任何其他地方)時,如var inst = new SuperClass();
,有效發生的是以下幾點:
prototype
-property。 在代碼中,這將是var temp = Object.create(SuperClass.prototype);
。 this
對象。 在代碼中,這將是SuperClass.call(temp, <arguments>)
。 inst
設置為該值,否則將其設置為temp
值。 現在,在您的SuperClass
函數中,您執行以下操作:
//Constructor implementation of this class
//public functions
return {
parentPublicFunction: function() {
//Public function implementation
}
}
function privateFunction() {
//Private function implementation.
}
這里發生的是,你的SuperClass
方法得到的以調用this
,這是一個實例SuperClass
,即。 它的原型鏈中有SuperClass.prototype
。 這意味着,如果您this instanceof SuperClass
,那么您將會如您所料那樣成為true
。 然后你去返回一個新的匿名對象,它有一個名為parentPublicFunction
的屬性(恰好是一個函數,但可以是任何東西)。 您返回的這個新對象不是SuperClass
的實例。 它的屬性中沒有SuperClass.prototype
。 您已經創建了一種情況,如果我這樣做(new SuperClass()) instanceof SuperClass
您就會得到錯誤。 換句話說,從SuperClass
構造函數返回的實例不會實現您的“類”。 這可能完全不是你想要的,這也是你不能僅僅在JavaScript上使用經典繼承原則並期望事物運行相同的原因之一。
現在,我們到目前為止,是一個函數名稱SuperClass
,它返回一個與SuperClass
沒有任何關系的Object
。 SuperClass
有一個空的原型,這意味着即使你以某種方式設法在其原型鏈中創建具有SuperClass.prototype
對象,它也不會從SuperClass
繼承任何東西,因為沒有任何定義可以繼承。 這將我們帶到了childClass
函數。
首先,我將命名為ChildClass
而不是childClass
。 您期望人們使用new
調用的JavaScript中的任何函數都應以大寫字母開頭。 您不希望使用new
調用的任何函數都應以小寫字母開頭。 在JavaScript中無法知道函數是否打算使用或不使用new
來調用,因此這用於表示。
現在, ChildClass.prototype
被設置為SuperClass
一個實例,這意味着SuperClass
原型中的任何方法都可以從ChildClass
的實例中調用。 而ChildClass
任何實例也是SuperClass
一個實例(就像你期望的那樣)。 但是,正如已經解釋過的那樣, SuperClass
的原型是空的,所以沒有什么可以繼承它。 因此, ChildClass
從此繼承中獲得的唯一事實是a instanceof ChildClass
意味着a instanceof SuperClass
。 但是,就像在SuperClass
,您從ChildClass
返回一個匿名對象,這又導致(new ChildClass()) instanceof ChildClass
為false。
其中,存在(大多數)你的問題。 解決方案只是為了了解OOP如何在JavaScript中運行並在執行JavaScript時接受它,而不是試圖將其彎曲到您認為工作的方式。
因為要從構造函數返回自己的對象,所以必須多做一些管道。
//Call to super constructor
this.parent.constructor.call(this, arguments);
返回SuperClass
的公共API,但是你沒有對結果做任何事情。 你必須將它合並到孩子的公共API中:
//Call to super constructor
var parentAPI = this.parent.constructor.call(this, arguments);
//Public function for childClass.
return Object.assign(parentAPI, {
childPublicFunction: function() {
//function implementation
}
});
在您的情況下,分配給childClass.prototype
實際上是無關緊要的,因為從構造函數返回的對象無論如何都不會從它繼承。 即childObj
將不具有您分配給原型的任何屬性(例如parent
)。 通過返回自己的對象,你會錯過更多的東西,例如能夠使用instanceOf
( childObj instanceOf childClass
將為false
)。
為了讓所有的工作,你必須在方法分配給this
構造函數中(而不是返回的對象)。 您可以在MDN文檔中找到有關該OOP樣式的更多信息。
注意:通常使用大寫字母(即ChildClass
來啟動構造函數的名稱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.