На прошлой неделе мы познакомились с вами с эффектом затенения. Что это за эффект? Мы можем на объекте определить метод или поле с тем же самым именем, что и в прототипе. При этом интерпретатор сохранит реализацию метода и значение поля в прототипе нетронутым и создаст копию этого метода или поля на стороне объекта. И в этом видео я вам покажу, каким образом мы можем вызывать затеняемый метод в затеняющем. Допустим, у нас есть некоторый конструктор Person, конструктор личностей, который на вход принимает имя этих личностей и кладет в поле name. Также мы определяем прототип для всех личностей с методом getName, который возвращает это имя. Положим этот прототип в хранилище конструктора Person. Далее мы захотим использовать в нашей программе объекты другого типа, например, студентов и создадим конструктор для них. Прототипом для них мы сделаем объект на основе прототипа для личностей, но захотим изменить метод getName. Нам не хочется дублировать тот прекрасный код, который есть в методе getName прототипа личностей, а лишь хотим немножечко его дополнить и добавлять к нему некую строку, например, мы хотим не просто возвращать имя, а возвращать «студент такое имя». Каким образом мы можем это сделать? Вначале нам может показаться, что мы можем вызвать просто метод getName из прототипа Person внутри метода getName прототипа для студентов. Но в этом случае произойдет рекурсивный вызов того же самого метода. И интерпретатор нам скажет, что количество вызовов заполнило весь стек. Почему это происходит? Когда мы вызываем метод getName у созданного нами студента, например, Billy, внутри этого метода this будет ссылаться, собственно, на этого самого студента. Так как метода getName у самого Billy нет, он пойдет искать его в прототипе и найдет метод в прототипе, который хранится в хранилище конструктора Student в поле Student.prototype. Фактически мы вызовем метод... Метод будет вызывать сам себя. Каким образом мы можем решить эту проблему? Самое простое — использовать другое название метода вместо эффекта затенения. В этом случае все будет работать. Мы будем вызывать метод с другим названием, например, getStudentName, заходить внутрь этого метода, this внутри него будет по-прежнему ссылаться на объект Student, то есть на Billy, попробуем найти у Billy метод getName, не найдем его там, пройдем по цепочке прототипов в объект, который хранится в хранилище конструктора студентов Student.prototype. И там мы этого метода не найдем, проследуем дальше по цепочке прототипов и уже перейдем в хранилище, которое хранится в конструкторе Person. Там мы этот метод находим, спокойно его вызываем, возвращаем имя студента, добавляем к нему наш необходимый префикс, и все работает, как нужно. Но такой метод решения этой проблемы выглядит немножко не элегантно. Более элегантным способом будет использование метода call. Мы можем напрямую в затеняющем методе вызывать затеняемый при помощи этого метода call, но передавать туда текущий контекст. А текущий контекст будет ссылаться на создаваемого объекта конструктора студентов, а именно на студента. Таким образом мы вызываем затеняемый метод от лица этого самого студента, спокойно получаем имя этого студента и добавляем к нему префикс student. Все работает, как нужно. В этом видео мы с вами познакомились со способом, который позволяет вызывать затеняемый метод в затеняющем.