Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > JavaScript: Общие вопросы > Наследование и сво-во "constructor" |
Автор: Се ля ви 3.6.2008, 15:46 | ||||||||||||||||||||||||||
Насколько я понял, наследование в JS реализуется за счёт того, что объект содержит в себе неявную ссылку на объект-предок в иерархии наследования (эта ссылка является явной для FF и называется "__proto__"). Но есть один нюанс: для объекта, расположенного по этой ссылке, должно выполняться требование, что его свойство "constructor" ссылается на функцию-конструктор объекта, а сам объект в случае необходимости получает ссылку на свой конструктор, как раз через эту самую неявную ссылку (в случае FF - явную - "__proto__"), вызывая свойство "constructor". Когда ScriptEngine не находит свойства "constructor" в объекте, она обращается к "__proto__" и пытается найти это свойство у объекта, расположенного по этому адресу. Таким образом, если мы смотрим на это хозяйство из объекта, то для FF справедливо следующее:
, так как на самом деле, поскольку
, происходит следующее:
Для остальных же браузеров, получается, что из объекта мы можем увидеть прототип только воспользовавшись правой частью первого тождества. Если эта цепочка из двух (а с неявным - трёх) вызовов нарушится, то объект не сможет явно увидеть свой прототип. Таким образом, когда мы производим наследование присвоением
, то после этого получается вот что:
, зато:
, поскольку
и
, так что фактически мы имеем следующее тождество:
, т.е. мы потеряли связь с конструктором объекта "childObj"! Авторы нескольких статей про JS-наследование специально указывают на этот момент и призывают после присвоения ссылке "prototype" объекта-предка присвоить ссылку на её "constructor":
Да, таким образом мы восстановили ссылку на конструктор объекта "childObj", но проблему мы эту решили, создав себе другую - теперь для всех браузеров, кроме FF, мы потеряли ссылку на конструктор объекта "parentObj"! Ведь теперь:
, так что
И только в FF мы можем написать
, а в остальных браузерах - кирдык. Думается, что использование длинных деревьев наследования обязательно спотыкнётся об это обстоятельство или по крайней мере создаст большие неудобства. Вот, собственно, и проблема - как это ограничение модели можно было бы на ваш взгляд обойти? |
Автор: SelenIT 3.6.2008, 20:50 |
Если не ошибаюсь, именно эту путаницу некогда разруливал Zeroglif http://forum.dklab.ru/viewtopic.php?p=102575#102575 к котеровской http://dklab.ru/chicken/nablas/40.html о наследовании в JS... |
Автор: Се ля ви 3.6.2008, 22:16 |
SelenIT, да, Zeroglif там это объяснил, но лекарства не дал - пост заканчивается констатацией этого факта и вопрос, что с этим делать не поднял. Может быть, там будет про это дальше - сейчас почитаю тему, всё-таки пять листов после этого... |
Автор: AKS 4.6.2008, 07:08 |
Се ля ви, я дочитал вот до этого (дальше пока не стал читать - с утра голову надо беречь ;) ): Вы ведь чуть выше написали: Вы явно немного запутались. А начать "распутывать" можно с этого: childObj.constructor.prototype = parentObj. Вот зачем это? |
Автор: Се ля ви 4.6.2008, 14:39 | ||
Так, забудьте, что я тут до этого написал. Давайте начнём заново? Я решил описать проблему в комментариях к коду. Комментариев получилось очень много, за то можно теперь весь этот текст загнать в редактор и, запустив в браузере (будет работать только в FF) понять, что всё работает именно так, как я расписываю. Так же весьма рекомендую периодически по ходу чтения поглядывать в http://www.mollypages.org/misc/jsobj_full.jpg, за которую большой "Thanks" Zeroglif`у.
Пока расписывал, нащупал решение проблемы и сейчас его тестирую. Как решу - напишу сюда. В любом случае получилось на мой взгляд весьма познавательное чтиво для тех, кто не очень хорошо разобрался в тонкостях реализации наследования в ECMAScript. |
Автор: Се ля ви 4.6.2008, 17:10 | ||
Завершил и проблема решилась. В ближайшее время переработаю это в нормальную статью. Вот полный вариант, изабильно снабжённый комментариями (фактически, это и есть статья из комментариев со вставками кода):
|
Автор: AKS 4.6.2008, 17:51 | ||
Это все ради того, чтобы получить возможность написать что-то, вроде:
? Или есть еще мотивы? |
Автор: AKS 5.6.2008, 11:20 | ||||
Ключевая фраза: "использование длинных деревьев... создаст большие неудобства". И это совершенно верно! На самом деле, мне просто жаль (честное слово ;) ) вашего времени, сил и энергии, которые могут быть напрасно истрачены. А ведь можно изменить подход и начать думать по-js’овски. Вот, специально для этого случая нашел кое-какие высказывания js-гуру (как раз есть кое-что по-поводу "длинных деревьев наследования" и прочей class-based мишуры):
Я подчеркнул на мой взгляд наиболее значимые моменты (если будут трудности с переводом. то могу помочь ;) ). Надеюсь, что эти высказывания опытных программистов как-нибудь когда-нибудь пригодятся... Happy scripting (как пишут англоязычные программисты)! ![]() |
Автор: Се ля ви 5.6.2008, 12:48 | ||
AKS, большое спасибо, что нашли эти высказывания! Это уже превращается в философскую дискуссию. Что бы было понятно по аналогии, приведу свою заметку в ЖЖ двухлетней давности:
Или другие мои рассуждения, касающиеся вопроса о свободе: Дождевой кольчатый червяк не имеет скелета и может изгибаться как ему заблагорассудится, как не может изгибаться ни один гимнаст. Более того, он обладает настолько простой структурой тела, что легко восстанавливается, если его разорвать - и будет два червяка. Но человек за счёт скелета и сложности строения организма, имеет прямохождение, которое если и может добиться червяк, встав на свои кончики, то оно дастся ему страшно большой потерей энергии и фактически недостижимо. Т.е. свобода в одном означает отсутсвие свободы в другом. В общем, все достоинства - они же и обратные стороны недостатков и тут нужен баланс в зависимости от того, чего хочется добиться. В Java, которой я занимаюсь, тоже есть феноменальная гибкость, но там эти методы вынесены в отдельный пакет java.reflection которым не принято пользоваться без необходимости - что бы не наводить бардака в программе. С её помощью тоже можно добавлять, удалять и заменять методы объектов, создавать классы на лету и делать всё что угодно, нарушая каноны class-based программирования, но это используют обычно только при написании сред разработки, в остальных приложениях использование Reflection API считается дурным тоном и используется по минимуму. И мощность и масштаб Java-приложений в итоге зашкаливает. А с другой стороны, не использование Reflection API подавляющим большинством программистов позволяет делать прекрасные средства разработки типа IntelliJ IDEA, которые очень сильно помогают при разработки больших приложений. Я представляю, насколько тяжело было людям разрабатывать тот же GMail, если они, как вы выражаетесь, мыслили по-js`овски. Мне хочется найти способ проще создавать большие приложения и для этого необходим иной компромисс жёсткости и гибкости для этого языка - и мне кажется, что пример в этом как раз и можно брать с Java. Вот я и пытаюсь выработать рекомендации по программированию на JS для того, что бы реализовать такой компромисс и сделать возможным создание хитрых web-интерфейсов и удобных средств для их разработки. ![]() |