Dědičnost
Dědičnost je proces, při kterém může být jeden objekt založen na jiném. Díky tomu mohou objekty vzájemně sdílet své vlastnosti.
Vytvořil jsem prototyp Hero
a použil ho k vytvoření nového objektu s názvem superman
. S tímto objektem však nic neděláme. Postaráme se tedy o to vytvořením další funkce s názvem dialogue
.
function dialogue() {
console.log('I am ' + this.name);
}
Pokud však nyní spustíme náš kód, nic se nestane, protože tato funkce neví, jaké je skutečné jméno. K tomu potřebujeme
Chci, aby tato nová funkce měla stejné vlastnosti jako funkce Hero
. Místo toho, abychom je zapisovali uvnitř této funkce, můžeme jednoduše říci JavaScriptu, aby je zdědil od prototypu Hero
.
To je možné pomocí vlastnosti prototype
, která je v JavaScriptu k dispozici v rámci libovolného objektu.
Díky umístění dialogue
na Hero.prototype
jsme ji zpřístupnili všem instancím Hero
.
Diferenciální dědičnost
JavaScript také přichází s dalším modelem dědičnosti, který se nazývá „diferenciální dědičnost“. V tomto modelu se metody nekopírují z rodiče na potomka. Ale místo toho existuje vazba mezi potomky a jejich rodičovským objektem.
Tady superman
vlastně nemá svou vlastní metodu s názvem dialogue()
. Jak ale potom funguje superman.dialogue()
?“
Když JavaScriptový engine narazí v kódu na superman.dialogue()
, hledá uvnitř objektu superman
vlastnost s názvem dialogue
. Když ji nenajde, vyhledá v řetězci prototypů nadřazený objekt superman
Hero.prototype
. Tam najde Hero.prototype.dialogue
a zavolá ji pomocí this
, který je svázán s superman
.
Objekt.create()
Tento postup můžeme ještě více vylučovat tím, že vytvoříme novou třídu Superman
, která bude dědit vlastnosti prototypu Hero
. Můžeme to udělat tak, že prototypu Superman
přiřadíme prototyp Hero
takto:
function Superman() {}
Superman.prototype = Hero.prototype
Ale to dělá to, že to prostě zrovnoprávní jak Superman
, tak Hero
. Ve skutečnosti potřebujeme nový objekt, který je založen na prototypu Hero
. Od verze ES5 obsahuje JavaScript vestavěnou funkci s názvem Object.create()
. Použijme ji zde, jak je uvedeno níže:
Superman.prototype = Object.create(Hero.prototype);
Tím se vytvoří nový prázdný objekt, který je založen na prototypu Hero
, a přiřadí se prototypu Superman
. Takže všechny vlastnosti, které máme v prototypu Hero
, jsou nyní přístupné prototypu Superman
. Takže místo volání new Hero
můžeme volat new Superman
a vše bude stále fungovat, jak má.
Pokud se však na výstup podíváte pozorněji, všimnete si, že uvnitř je undefined
. To proto, že v současné době je Hero
konstruktor pouze sám pro sebe. Musíme call
vlastnosti Hero
uvnitř prototypu Superman
.
function Superman() {
Hero.call(this, 'Superman', 'Clark Kent', 'Krypton')
}
Vytvoříme další konstruktor s názvem MarvelMovies
, jak je uvedeno níže:
function MarvelMovies(movieName, releaseYear) {
this.movieName = movieName;
this.releaseYear = releaseYear;
}
Pokud je funkce použita jako konstruktor, this
odkazuje na nový objekt, který vytváříme. V tomto konstruktoru jsem tedy vzal jako argumenty movieName
a releaseYear
a přiřadil tyto hodnoty vlastnostem movieName
a releaseYear
naší nové instance MarvelMovies
s názvem avengers
.
var avengers = new MarvelMovies("avengers", 2012);
Pro tento prototyp pak vytvořím novou metodu s názvem output
, jak je uvedeno níže:
MarvelMovies.prototype.output = function() {
return "Movie: " + this.movieName + " Released in " + this.releaseYear;
}
console.log(avengers.output());
Příští dědičnost
Vskutku skvělým aspektem dědičnosti je to, že JavaScript umožňuje upravovat nebo rozšiřovat vlastnosti třídy i poté, co jste ji definovali.
JavaScript při pokusu o přístup k vlastnostem objektu vyhledá prototyp. Třídy tedy můžete za běhu měnit!
Pro ilustraci vytvoříme pole podle následujícího obrázku:
var numbers = ;
Array.prototype.shuffle = function() {
return this.sort(function() {
return Math.round( Math.random() * 2) - 1;
});
};
console.log(numbers.shuffle());
Tady pole numbers
existovalo dříve než Array.prototype.shuffle
. V JavaScriptu však vyhledávání vlastností probíhá až v řetězci prototypů. Proto pole stále získává přístup k nové metodě shuffle
, protože existuje na Array.prototype
, když se ji skutečně snažíme použít.
Zjednodušeně řečeno, vytvořili jsme pole, pak jsme se vrátili zpět a dali všem polím přístup k nové metodě.