我們已經在使用JavaScript的構造函數,來創建自己的自定義對象類型。但是,我們並沒有看到如何創建一個繼承層次結構。
重要的是,雖然構造函數通常被稱為“類”,但他們真的是不一樣的東西。在JavaScript中,一個構造函數就是在new
一個對象時調用的函數。
這里有一個小復習:
function SuperHuman (name, superPower) { this.name = name; this.superPower = superPower; } SuperHuman.prototype.usePower = function () { console.log(this.superPower + "!"); }; var banshee = new SuperHuman("Silver Banshee", "sonic wail"); // 輸出: "sonic wail!" banshee.usePower();
SuperHuman的構造包含了初始化邏輯,而SuperHuman.prototype包含了所有SuperHuman的實例的共享方法。
但是假設我們要建立一個新的類型,繼承自SuperHuman,同時增加自己的功能。那么,具體會怎么樣?
function SuperHero (name, superPower) { this.name = name; this.superPower = superPower; this.allegiance = "Good"; } SuperHero.prototype.saveTheDay = function () { console.log(this.name + " saved the day!"); }; var marvel = new SuperHero("Captain Marvel", "magic"); // 輸出: "Captain Marvel saved the day!" marvel.saveTheDay();
有幾個問題。首先,SuperHero
的構造函數被重復一些 SuperHuman
的構造函數的邏輯。並且更重要的是,在這一點上SuperHero
的實例沒有獲得 SuperHuman
的方法。例如:
// TypeError: Object <#SuperHero> has no method 'usePower' marvel.usePower();
讓我們來解決這些問題。
function SuperHero (name, superPower) { // Reuse SuperHuman initialization SuperHuman.call(this, name, superPower); this.allegiance = "Good"; } SuperHero.prototype = new SuperHuman(); SuperHero.prototype.saveTheDay = function () { console.log(this.name + " saved the day!"); }; var marvel = new SuperHero("Captain Marvel", "magic"); // Outputs: "Captain Marvel saved the day!" marvel.saveTheDay(); // Outputs: "magic!" marvel.usePower();
我們已經成功通過調用SuperHuman與SuperHero的這個對象,並傳遞所需的參數,以消除重復的構造邏輯。這確保了SuperHuman的初始化邏輯將擔任新的SuperHero對象。然后,我們套上了額外的邏輯是特定SuperHuman。
但是,為了確保SuperHero.prototype繼承SuperHuman.prototype的方法,我們實際上new SuperHuma() 了一個實例。
這個基本的遺傳模式並不總是可行的,特別是如果父類的構造是復雜的,但它會處理簡單的情況相當不錯。
在未來的問題,我們將看看在做傳承更復雜的方式。