Список вопросов для интервью на этой неделе:
- Какова основная идея наследования цепочки прототипов? Каковы плюсы и минусы?
- Какова основная идея заимствования конструкторов и наследования композиции? Каковы плюсы и минусы?
- Какова основная идея прототипного наследования? Каковы плюсы и минусы?
- В чем заключается основная идея паразитарного наследования? Каковы плюсы и минусы?
- В чем заключается основная идея наследования паразитарного состава? Каковы плюсы и минусы?
На этой неделе мы поговорим о наследовании. Прежде чем мы начнем, нам нужно разобраться в конструкторах, прототипах и цепочках прототипов.
Более качественные изделия можно штамповать: GitHub.com/Иветт Л.А. Ю/Б…
Конструктор
Отличие конструкторов от обычных функций только в способе их вызова.newоператор, его можно использовать как конструктор, любая функция, которая не передаетnewоператора для вызова, то это нормальная функция.
экземпляр владеетconstructor(构造函数)Свойство, которое возвращает конструктор, создавший объект экземпляра.
Следует отметить, что помимо основных типов данныхconstructorза пределами(nullа такжеundefinedбезconstructorатрибуты),constructorСвойства могут быть переопределены. Таким образом, при определении типа объектаinstanceofкоэффициент оператораconstructorболее надежный.
прототип
Каждая функция, которую мы создаем, имеетprototypeсвойство, это свойство указывает на объект-прототип функции. прототип объектаиспользоватьОн содержит свойства и методы, которые могут быть общими для всех экземпляров определенного типа.
По умолчанию все объекты-прототипы автоматически получаютconstructorсвойство, это свойство содержит указатель наprototypeУказатель на функцию, в которой находится свойство.
Когда конструктор вызывается для создания нового экземпляра, этот экземпляр будет содержать указатель на объект-прототип конструктора (доступ к которому можно получить через класс экземпляра).__proto__для доступа к прототипу объекта конструктора).
实例.__proto__ === 构造函数.prototype
console.log(Object.prototype.__proto__ === null) //true
console.log(Object.__proto__ === Function.prototype) //true
console.log(Function.prototype.__proto__ === Object.prototype) //true
Сеть прототипов
Кратко рассмотрим отношения между конструкторами, прототипами и экземплярами:
Каждый конструктор имеет объект-прототип, все объекты-прототипы содержат указатель на конструктор, а все экземпляры содержат внутренний указатель, который может указывать на объект-прототип (доступ к которому можно получить через__proto__доступ).
Если сделать объект-прототип равным экземпляру другого типа, то объект-прототип содержит указатель на другой прототип и, соответственно, другой прототип также содержит указатель на другой конструктор. Если другой прототип является экземпляром другого типа, то указанное выше отношение остается в силе, и таким образом формируется цепочка экземпляров и прототипов, что является основным понятием цепочки прототипов.
Одна картинка стоит тысячи слов:
передачаinstance.getType()Выполняются следующие шаги поиска:
- поиск
instanceПример - поиск
SimType.prototype - поиск
SubType.prototype - поиск
SuperType.prototype, нашел этоgetTypeметод
Когда свойство или метод не найдены, процесс поиска всегда останавливается в конце цепочки прототипов, цикл за циклом.
Все ссылочные типы наследуютObject, это наследование также достигается через цепочку прототипов. если вSuperType.prototypeеще не получилgetType, прибудетObject.prototypeНайдите его посередине (на картинке на одно звено меньше).
Наследование цепочки прототипов
Основная идея наследования цепочки прототипов состоит в том, чтобы использовать прототип, чтобы позволить одному ссылочному типу наследовать свойства и методы другого ссылочного типа.
Такие какSubType.prototype = new SuperType();
Как можно заметитьcolorsСвойства являются общими для всех экземпляров (экземпляр1, экземпляр2, ...).
недостаток:
- Когда наследование реализуется через прототип, прототип становится экземпляром другого типа, исходное свойство экземпляра становится текущим свойством прототипа, а свойство ссылочного типа прототипа будет общим для всех экземпляров.
- При создании экземпляра подтипа невозможно передать аргументы конструктору супертипа, не затрагивая все экземпляры объекта.
Заемный конструктор
Заемный конструктортехнологии, ее основная идея заключается в следующем:
Вызвать конструктор супертипа в конструкторе подтипа.
преимущество:
- Параметры могут быть переданы в суперкласс
- Исправлена проблема, из-за которой значения ссылочного типа, содержащиеся в прототипах, были общими для всех экземпляров.
недостаток:
- Методы определены в конструкторе, повторное использование функции невозможно, кроме того, методы, определенные в прототипе супертипа, невидимы для подтипа.
наследование композиции
Комбинаторное наследование относится к шаблону наследования, который сочетает в себе цепочку прототипов и заимствованную технологию конструктора, чтобы использовать их сильные стороны. Основная идея:
Используйте цепочку прототипов для реализации наследования свойств и методов прототипа и реализации наследования свойств экземпляра путем заимствования конструкторов, что не только реализует повторное использование функций путем определения методов в прототипе, но и гарантирует, что каждый экземпляр имеет свои собственные свойства.
недостаток:
- В любом случае конструктор супертипа вызывается дважды: один раз при создании прототипа подтипа и один раз внутри конструктора подтипа.
преимущество:
- Параметры могут быть переданы в суперкласс
- Каждый экземпляр имеет свои свойства
- повторное использование функции
прототипное наследование
Основная идея прототипного наследования:
Прототипы позволяют создавать новые объекты на основе существующих объектов без необходимости создавать для них пользовательские типы.
существуетobject()Внутри функции сначала пробить временный конструктор, затем использовать входящий объект в качестве прототипа этого конструктора и, наконец, вернуть новый экземпляр этого временного типа, по сути,object()Неглубокая копия выполняется для переданного объекта.
ECMAScript5, добавивObject.create()Методы стандартизируют прототипное наследование. Этот метод принимает два параметра: объект для использования в качестве прототипа нового объекта и (необязательно) объект для определения дополнительных свойств для нового объекта (которые могут переопределять одноименные свойства объекта-прототипа). передача одного параметра,Object.create()а такжеobject()Метод ведет себя так же.
Прототипное наследование хорошо работает в ситуациях, когда нет необходимости создавать конструкторы, а нужно лишь сохранить один объект похожим на другой.
недостаток:
Подобно наследованию цепочки прототипов, свойства, содержащие значения ссылочного типа, являются общими для всех экземпляров.
паразитарное наследование
Паразитическая наследственность — это идея, тесно связанная с прототипической наследственностью. Идея паразитического наследования аналогична паразитическому конструктору и шаблону фабрики, т.е. создать функцию, которая просто инкапсулирует процесс наследования, который каким-то образом внутренне улучшает объект, и, наконец, действует так, как будто он действительно сделал всю работу. объект.
на основеpersonвозвращает новый объект ---person2, новый объект не только имеетpersonВсе свойства и методы , а также собственныеsayHi()метод. Паразитическое наследование также является полезным шаблоном при рассмотрении объектов, а не пользовательских типов и конструкторов.
недостаток:
- Использование паразитного наследования для добавления функций к объектам неэффективно из-за невозможности повторного использования функций.
- Подобно наследованию цепочки прототипов, свойства, содержащие значения ссылочного типа, являются общими для всех экземпляров.
Паразитическая композиционная наследственность
Так называемое паразитическое комбинированное наследование означает наследование свойств путем заимствования конструкторов и наследование методов через смешанную форму цепочки прототипов.Основная идея заключается в следующем:
Вместо того, чтобы вызывать конструктор супертипа для указания прототипа подтипа, все, что нам нужно, — это копия прототипа супертипа, по существу используя паразитное наследование для наследования прототипа супертипа и последующего присвоения результата прототипу прототипа подтипа. Основная модель паразитарного композиционного наследования выглядит следующим образом:
- Шаг 1: Создайте копию прототипа супертипа
- Шаг 2: Добавьте в созданную копию
constructorАтрибуты - Шаг 3: Назначьте вновь созданный объект прототипу подтипа
В этот момент мы можем позвонитьinheritPrototypeзаменить оператор, присваивающий прототипу подтипа:
преимущество:
Конструктор суперкласса вызывается только один раз, что более эффективно. избегать вSuberType.prototypeВышеупомянутое создает ненужные, избыточные свойства, сохраняя цепочку прототипов нетронутой.
Поэтому паразитное наследование композиции является наиболее рациональной парадигмой наследования для ссылочных типов.
Наследование ES6
ClassНаследование может быть достигнуто с помощью ключевого слова extends, например:
Для ES6classНеобходимо сделать следующие пункты:
- Тип данных класса — это функция, а сам класс указывает на конструктор.
console.log(typeof SuperType);//function
console.log(SuperType === SuperType.prototype.constructor); //true
- Все методы, определенные внутри класса, не являются перечисляемыми. (Методы прототипов ES5 по умолчанию являются перечисляемыми)
Object.keys(SuperType.prototype);
-
constructorметод является методом класса по умолчанию, черезnewЭтот метод вызывается автоматически, когда команда создает экземпляр объекта. Класс должен иметьconstructorметод, если он не определен явно, пустойconstructorМетод будет добавлен по умолчанию. -
ClassЕго нельзя вызвать напрямую, как конструктор, он выдаст ошибку.
использоватьextendsКлючевое слово реализует наследование, одна вещь требует особого пояснения:
- Подклассы должны быть в
constructorвызыватьsuperметод, иначе будет сообщено об ошибке при создании нового экземпляра. Если подкласс не определенconstructorметод, то этот метод будет добавлен по умолчанию. В конструкторе подкласса вызовите толькоsuperПосле этого вы можете использоватьthisключевое слово, иначе будет сообщено об ошибке. Это связано с тем, что конструкция экземпляра подкласса основана на экземпляре родительского класса, и только суперметод может вызвать экземпляр родительского класса.
(1) Атрибут __proto__ подкласса, указывающий на наследование конструктора, всегда указывает на родительский класс.
(2) Свойство __proto__ свойства прототипа подкласса, указывающее на наследование метода, всегда указывает на свойство прототипа родительского класса.
Кроме того, после того, как наследование Class скомпилировано с помощью babel, это паразитное наследование композиции ES5.
Справочная статья:
[1] [Расширенное программирование на JavaScript, глава 6]
[2] ES6 Class
Спасибо за вашу готовность потратить свое драгоценное время на чтение этой статьи. Если эта статья дала вам небольшую помощь или вдохновение, пожалуйста, не скупитесь на лайки и звезды. Вы, безусловно, самая большая движущая сила для меня, чтобы двигаться вперед .GitHub.com/Иветт Л.А. Ю/Б…
В коде в этой статье используются изображения. Если вы хотите скопировать код напрямую, перейдите по ссылке[Шаг за шагом] Углубленный анализ часто задаваемых вопросов интервью / Еженедельник 06