Наследование объектов является объектно-ориентированным принципом и обеспечивает возможность доступа к методам и свойствам другого объекта (родительского) из производного объекта (дочернего). Наследование в javascript возможно через прототип или наследование по прототипу.
JavaScript предоставляет ключевое слово class — ключевое слово class было введено в ES2015, но это синтаксический сахар, JavaScript остается основанным на прототипах — для объявления классов и extends для наследования. В этой заметке я использую подход с использованием функций и прототипов для детализации процесса наследования и цепочки прототипов.
Цепочка прототипов (процесс поиска прототипа)
В javascript, когда мы обращаемся к свойству объекта, движок javascript проверяет, существует ли это свойство в объекте, и если не находит, то ищет его в прототипе объекта*, а если не находит, то ищет в прототипе прототипа и так далее, проходя через все унаследованные экземпляры, пока не достигнет последнего прототипа. Если он не найдет его, JS вернет неопределенное значение.
Для доступа к информации прототипа мы используем __proto__
и с его помощью можем получить доступ к информации других прототипов выше (более общих).
Рассмотрим следующий пример, в котором у нас есть три объекта, где низший класс Director наследует характеристики от Teacher и Employee:
function Funcionario() {}
Funcionario.prototype.salario = () => 'R$ 10000'
function Professor() {}
Professor.prototype = Object.create(Funcionario.prototype)
Professor.prototype.horaExtra = () => 'R$ 500'
function Diretor() {}
Diretor.prototype = Object.create(Professor.prototype)
Diretor.prototype.bonus = () => 'R$ 2000'
Теперь давайте инициализируем объект Principal и обратимся к унаследованному методу salary():
const diretor = new Diretor();
console.log(diretor.salario()); //output => 'R$ 10000'
Это стало возможным потому, что когда мы вызвали метод salary(), механизм javascript проверил, существует ли этот метод в прототипе Director, и когда не нашел, он пошел «вверх», переходя от прототипа к прототипу, пока не нашел метод в прототипе Employee.
Используйте __proto__
и посмотрите цепочку прототипов через самый нижний экземпляр, которым является Director:
console.log(diretor.__proto__) //output => prototype Diretor
console.log(diretor.__proto__.__proto__) //output => prototype Professor
console.log(diretor.__proto__.__proto__.__proto__) //output => prototype Funcionario
Заключение
Очень важно хорошо понимать «наследование прототипов» в javascript, чтобы писать сложный код. Не допускайте, чтобы цепь вашего прототипа была большой, и при необходимости разрывайте цепь, чтобы избежать проблем с производительностью.