Vysvětlete, jak funguje dědičnost v JavaScriptu.
sobes.tech AI
Odpověď od AI
Dědičnost v JavaScriptu je realizována přes prototypy. Každý objekt v JavaScriptu má vnitřní vlastnost [[Prototype]], která odkazuje na jiný objekt. Když se pokusíme získat přístup k vlastnosti nebo metodě objektu, která přímo u něj není, JavaScript engine hledá tuto vlastnost nebo metodu v prototypu tohoto objektu. Pokud ji nenajde, pokračuje v hledání po řetězci prototypů, který je tvořen spojeními [[Prototype]], dokud nedosáhne null (konec řetězce).
Existují dva hlavní mechanismy dědičnosti:
-
Klasická prototypová dědičnost (ES5 a dříve): Je založena na použití konstrukčních funkcí a jejich vlastnosti
prototype.// Konstrukční funkce function Zvíře(jméno) { this.jméno = jméno; } // Přidání metody do prototypu Zvíře.prototype.mluví = function() { console.log(`${this.jméno} vydává zvuk.`); }; // Vytvoření instance const pes = new Zvíře('Pes'); // Volání metody z prototypu pes.mluví(); // Výstup: Pes vydává zvuk. // Prototyp `dog` je `Zvíře.prototype` console.log(Object.getPrototypeOf(pes) === Zvíře.prototype); // true -
Třída (ES6 a novější): Používá syntaktický cukr
classaextends, který pod kapotou stále pracuje s prototypy.// Základní třída class Zvíře { constructor(jméno) { this.jméno = jméno; } mluví() { console.log(`${this.jméno} vydává zvuk.`); } } // Podtřída, dědí z Zvíře class Pes extends Zvíře { constructor(jméno, plemena) { super(jméno); // Volání konstruktoru rodičovské třídy this.plemena = plemena; } štěká() { console.log(`${this.jméno} štěká.`); } } // Vytvoření instance podtřídy const můjPes = new Pes('Bublik', ['Labrador', 'Collie']); // Volání metod jak z Zvíře, tak z Pes můjPes.mluví(); // Výstup: Bublik vydává zvuk. můjPes.stěká(); // Výstup: Bublik štěká. // Prototyp `Pes.prototype` je `Zvíře.prototype` console.log(Object.getPrototypeOf(můjPes) === Pes.prototype); // true // Prototyp `Pes.prototype` je `Zvíře.prototype` console.log(Object.getPrototypeOf(Pes.prototype) === Zvíře.prototype); // true
Klíčové koncepty:
-
Řetězec prototypů: Spojení mezi objekty přes jejich
[[Prototype]]. -
__proto__(zastaralé/nestandardní, ale užitečné pro pochopení): Vlastnost, přes kterou lze získat přístup k[[Prototype]]. Nedoporučuje se používat v produkčním kódu. -
Object.getPrototypeOf(obj): Standardní způsob získání prototypu objektu. -
Object.setPrototypeOf(obj, proto): Standardní způsob změny prototypu objektu (nedoporučuje se měnit prototypy u již existujících objektů po jejich vytvoření). -
instanceof: Operátor pro kontrolu, zda je objekt instancí třídy nebo konstrukční funkce, prostřednictvím kontroly jeho řetězce prototypů.console.log(můjPes instanceof Pes); // true console.log(můjPes instanceof Zvíře); // true console.log(můjPes instanceof Object); // true (na konci řetězce je `Object.prototype`) -
super: Používá se v třídách k volání metod nebo konstruktoru rodičovské třídy.
Rozdíl mezi klasickým a třídním přístupem: Třídy poskytují strukturovanější a syntakticky pohodlnější způsob práce s prototypovým děděním, podobně jako v jiných programovacích jazycích. Nicméně základní mechanismus zůstává stejný — dědění přes prototypy.