Это обновление из другого моего поста, и, как оказалось, оно немного вводило в заблуждение.
Для тех, кто сразу попал на этот пост, вот что я собираюсь сделать: представить концепции наследования с помощью JavaScript словами, которые я использовал, чтобы понять их сам.
Для начала представим один из самых часто задаваемых вопросов на фронтенд-интервью,
В чем разница между классическим и прототипным наследованием в JS?
или это альтер-эго,
Как вы реализуете классическое наследование и прототипное наследование в JS?
или иногда более общий,
Расскажите о наследовании в JavaScript
Теперь есть несколько способов достижения наследования с помощью JavaScript, и они были разделены на две школы:
- Классический
- Прототип
Начнем с классического наследования.
Как следует из названия, это связано с классами или чертежами.
Java-способ сделать это будет примерно таким:
https://gist.github.com/rohanBagchi/f48e13f8bcbb059602f92a149ec015a4
Так вот, JavaScript из-за времени его изобретения должен был выглядеть как Java.
Для отношения Employee
и Accountant
это можно сделать в JavaScript, который имитирует поведение классов.
Employee
и Accountant
— это карты или чертежи, которые определяют, как должен выглядеть результирующий объект.
Это создает тесную связь между родителем и дочерним элементом, в нашем случае Employee
и Accountant
.
Эта строка:
Accountant.prototype = Object.create(Employee.prototype);
Он был добавлен для того, чтобы JS работал с магией, основанной на прототипах.
Видите ли, мы добавили новый метод в прототип Employee
после определения Accountant
.
Employee.prototype.sayName = function() { return `My name is ${this.name}`; };
Из-за нашего сопоставления прототипа Accountant
с прототипом Employee
мы теперь можем получить доступ к методам, определенным в родительском объекте.
Это классическое или классовое наследование в JavaScript.
Переходим к прототипному наследованию
Этот, как следует из названия, имеет какое-то отношение к прототипам или экземплярам объектов.
Их можно условно разделить на 2 типа:
- Конкатенация (с фабричными функциями)
- Прототип делегирования
Concatenative проще всего рассуждать, и любой, кто работает с react/redux, использовал бы его изо дня в день.
Все сводится к использованию restspread ES6 или Object.assign.
const Employee = { name: 'John Doe' }; const Accountant = { ...Employee, role: 'accountant' };
Этот шаблон становится более удобным, когда фабричные функции возвращают объекты:
const getEmployee = name => ({ name }); const getAccountant = name => ({ ...getEmployee(name), role: 'Accountant' });
Делегирование прототипа связано со свойством __proto__
всех объектов JS.
По сути, это работает как неявная ссылка на другой объект.
const Employee = { name: 'John Doe' }; const Accountant = { role: 'accountant' }; Accountant.__proto__ = Employee;
И это все, что нужно для понимания наследования.
Спасибо за чтение.
Найдите меня на linkedin или в твиттере @rohanBagchi или вернитесь ко мне в комментариях.
Меня зовут Рохан. Я пишу о технологиях, в основном о JavaScript: React, Redux, реактивные истории производительности приложений и инженерия интерфейса.