Обяснете как работи наследяването в JavaScript.
sobes.tech AI
Отговор от AI
Наследяването в JavaScript се реализира чрез прототипи. Всеки обект в JavaScript има вътрешно свойство [[Prototype]], което сочи към друг обект. Когато се опитваме да достъпим свойство или метод на обект, който не е директно при него, JavaScript движката търси това свойство или метод в прототипа на този обект. Ако не го намери там, продължава търсенето по веригата от прототипи, която се образува чрез връзките [[Prototype]], докато достигне null (края на веригата).
Съществуват два основни механизма за наследяване:
-
Класическо прототипно наследяване (ES5 и по-рано): Основава се на използването на конструкторски функции и техните свойства
prototype.// Конструкторска функция function Животно(име) { this.име = име; } // Добавяне на метод към прототипа Животно.prototype.говори = function() { console.log(`${this.име} издава звук.`); }; // Създаване на екземпляр const куче = new Животно('Куче'); // Викаме метод от прототипа куче.говори(); // Изход: Куче издава звук. // Прототипът `dog` е `Животно.prototype` console.log(Object.getPrototypeOf(куче) === Животно.prototype); // true -
Класическо наследяване (ES6 и по-късно): Използва синтаксиса
classиextends, който под капака пак работи с прототипи.// Основен клас class Животно { constructor(име) { this.име = име; } говори() { console.log(`${this.име} издава звук.`); } } // Подклас, наследяващ от Животно class Куче extends Животно { constructor(име, породи) { super(име); // Вика конструктора на родителския клас this.породи = породи; } лае() { console.log(`${this.име} лае.`); } } // Създаване на екземпляр от подклас const моетоКуче = new Куче('Bublik', ['Labrador', 'Collie']); // Викаме методи както от Животно, така и от Куче моетоКуче.говори(); // Изход: Bublik издава звук. моетоКуче.лае(); // Изход: Bublik лае. // Прототипът `Куче.prototype` е `Животно.prototype` console.log(Object.getPrototypeOf(моетоКуче) === Куче.prototype); // true // Прототипът `Куче.prototype` е `Животно.prototype` console.log(Object.getPrototypeOf(Куче.prototype) === Животно.prototype); // true
Ключови концепции:
-
Веригата от прототипи: Връзката между обектите чрез техните
[[Prototype]]. -
__proto__(остаряло/нестандартно, но полезно за разбиране): Свойство, чрез което може да се достъпи[[Prototype]]. Не се препоръчва за използване в продукционен код. -
Object.getPrototypeOf(obj): Стандартният начин да се получи прототипът на обект. -
Object.setPrototypeOf(obj, proto): Стандартният начин да се промени прототипът на обект (не се препоръчва за промяна на прототипа на вече съществуващи обекти след създаването им). -
instanceof: Оператор за проверка дали обектът е инстанция на даден клас или конструкторска функция, чрез проверка на веригата от прототипи.console.log(моетоКуче instanceof Куче); // true console.log(моетоКуче instanceof Животно); // true console.log(моетоКуче instanceof Object); // true (в края на веригата е `Object.prototype`) -
super: Използва се в класове за извикване на методи или конструктора на родителския клас.
Разликата между класическото и класовото подходи: Класовете предоставят по-структуриран и синтактично удобен начин за работа с прототипното наследяване, подобно на други програмни езици. Въпреки това, основният механизъм остава същият — наследяването чрез прототипи.