Соглашение о наследовании прототипов в JavaScript

Я вижу много такого кода:

function Base() {}
function Sub() {}
Sub.prototype = new Base();

Однако если вы это сделаете:

s = new Sub();
print(s.constructor == Sub);

Это неправда. Меня это сбивает с толку, поскольку конструктором s действительно является Sub. Традиционно / лучше ли это делать?

function Base() {}
function Sub() {}
Sub.prototype = new Base();
Sub.prototype.constructor = Sub;

или это неважно?

Я просто провел сравнение через html-страницу как предупреждение (s.constructor == Sub), и оно вернуло true.

GR1000 31.12.2008 21:13

Многие фреймворки настраивают свойство constructor, чтобы правильно указывать на конструктор подкласса. У меня есть сообщение, посвященное этой и другим проблемам в коде, который вы указали выше. js-bits.blogspot.com/2010/08/…

Juan Mendes 15.05.2012 04:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
2
1 852
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы хотите проверить, является ли объект в точности экземпляром Sub, используйте оператор instanceof: -

print(s instanceof Sub);

Если вы хотите узнать, является ли объект экземпляром Sub или экземпляром подкласса Sub, используйте метод isPrototypeOf: -

print(Sub.prototype.isPrototypeOf(s));
Ответ принят как подходящий

«конструктор» не делает того, что кажется. Это, помимо его нестандартности, является хорошей причиной избегать его использования - придерживайтесь instanceof и prototype.

Технически: «конструктор» не является свойством экземпляра «s», это свойство просматриваемого объекта-прототипа «Sub». Когда вы создаете функцию Sub в Mozilla, вы получаете недавно созданный объект Sub.prototype по умолчанию, который имеет «конструктор», указывающий на функцию Sub в качестве любезности.

Однако затем вы заменяете этот прототип новым Base (). Исходный прототип по умолчанию со ссылкой на Sub теряется; вместо этого Sub.prototype является экземпляром Base без какого-либо переопределяющего свойства «конструктор». Так:

new Sub().constructor===
Sub.prototype.constructor===
new Base().constructor===
Base.prototype.constructor===
Base

... вплоть до самого простого объекта, прототип которого вы не меняли.

Is it conventional/better to do this?

При работе с объектами / классами JavaScript нет единого соглашения; система метаклассов каждой библиотеки ведет себя немного по-разному. Я не видел ни одного, который записывал бы «конструктор» в каждый производный класс вручную, но он кажется таким же хорошим решением, как и любое другое, если вы действительно хотите иметь доступный реальный конструктор; он также сделает код совместимым с браузерами / движками, которые не предоставляют вам «конструктор».

Я бы подумал о том, чтобы дать ему другое имя, чтобы избежать путаницы с существующим свойством «конструктор», которое ведет себя иначе.

Ага,

Sub.prototype.constructor = Sub;

давайте использовать instanceof, но есть лучшее решение. Посмотрите здесь:, Наследование TDD JS на GitHub, и найдите шаблон Наследование паразитарных комбинаций. Код написан в TDD, поэтому вы сможете очень быстро его разобрать, а затем просто изменить имена, чтобы начать работу. Это в основном то, что использует YAHOO.lang.extend (источник: сотрудник yahoo и автор статьи Николаса Закаса «Профессиональный JavaScript для веб-разработчиков», 2-е издание, стр. 181). Кстати, хорошая книга (никак не аффилированная!)

Почему? Поскольку классический шаблон, с которым вы работаете, имеет статические ссылочные переменные (если вы создадите var arr = [1,2] в базовом объекте, ВСЕ экземпляры будут иметь чтение / запись и будут "разделять состояние" 'arr'! Если вы используйте кражу конструктора, вы можете обойти это. См. мои примеры.

Другие вопросы по теме