簡體   English   中英

JavaScript從子對象調用父函數

[英]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(); ,有效發生的是以下幾點:

  1. JavaScript創建一個新的空白對象,該原型等於您正在調用的函數的prototype -property。 在代碼中,這將是var temp = Object.create(SuperClass.prototype);
  2. JavaScript使用該對象調用您的函數作為this對象。 在代碼中,這將是SuperClass.call(temp, <arguments>)
  3. 如果函數返回任何內容,則將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 )。 通過返回自己的對象,你會錯過更多的東西,例如能夠使用instanceOfchildObj instanceOf childClass將為false )。

為了讓所有的工作,你必須在方法分配給this構造函數中(而不是返回的對象)。 您可以在MDN文檔中找到有關該OOP樣式的更多信息。


注意:通常使用大寫字母(即ChildClass來啟動構造函數的名稱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM