![]() |
Модераторы: Sardar, Aliance |
![]() ![]() ![]() |
|
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Думаю, лучше всего решить это инструментальными средствами - в средах программирования или обфускатором-оптимизатором JavaScript-кода - надо только присмотреть наиболее удачный и расширяемый и дописать к нему эту функциональность. В итоге, я думаю, можно будет написать объект в простой схеме наследования и она автоматом при оптимизации преобразуется в лёгкую (про себя вторую я называю так). Я уже продумываю этот момент ![]() -------------------- |
|||
|
||||
Се ля ви |
|
||||||||||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Несколько улучшений для лёгкой модели:
1. Вызов метода init:
Т.е. я предлагаю считать заявленные непосредственно в конструкторе параметры обязательными, а все параметры сверх - необязательными и с этих позиций мы вызываем метод init, передавая ему все параметры, переданные конструктору, только в случае, если параметров передано не меньше, чем заявлено в объявлении конструктора. 2. В методе init вызов метода init для предка производим так:
3. Избавляемся от постоянных строчек "this.privateState._get();" и "this.privateState._set();" в каждом public методе, необходимости всякий раз объявлять какую-либо переменную (например, "result") и присваивания ей значения private`ного поля перед его возвратом (для выполнения "this.privateState._set();"), а так же выбрасываем логику подсчёта вызовов в объекте privateState за счёт создания специального private-метода
и одной строчки вызова его в начале каждого public метода, которую предлагаю помещать сразу после открытия блока функции дабы она не мешалась с основной логикой метода:
, т.е. всю работу по взятию и сохранению данных из privateState за нас выполняет этот метод, а наличие или отсутствие экспортируемых данных определяется по переменной _super, которая должна быть у любого объекта всегда (если он ни от кого не наследуется, тогда она должна принимать значение Object.prototype:
В общем, работающий код лёгкой модели:
И всё бы хорошо, но... есть проблема:
Т.е. теперь ни класс, ни объект не распознаются оператором instanceof как экземпляры конструктора F... Нехорошо... ![]() У кого-нибудь есть по этому поводу какие-нибудь предложения? -------------------- |
||||||||||||||
|
|||||||||||||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
Се ля ви, у вас там ошибка в строке "return new this.constructor().init.apply(null, arguments);" (FireBug выдает), поэтому пока особо не вникаю, пофиксите. По поводу instanceof (тоже при беглом просмотре) - в 18 строке (this.constructor.prototype = new this.constructor.prototype.constructor;) вы подменяете прототип конструктора. Поэтому (new F).__proto__ уже не сравнивается с прототипом F, но сравнивается с прототип E (и даже прототипом Object):
P.S.: и все-таки (повторюсь в 10 раз - из-за особенностей языка), больше подошло бы "optimized heavy model of ..." |
|||
|
||||
Се ля ви |
|
||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Да, я уже пофиксил, просто не пойму, как можно конструктору объекта пареметры передать из arguments? При вызове обычной функции fnName.apply(this, arguments) работает, а вот если перед этим появляется ключевое слово new, возникает ошибка... Да, я как раз только что копал реализацию Rhino (это как раз реализация ScriptEngine от разработчиков проекта Mozilla). Нашёл вот это:
, а jsDelegatesTo реализован вот как:
Мда... Но я не могу иначе - мне обязательно нужно создавать отдельный прототип для каждого объекта наследника, иначе как сделать так, что бы внутреннее состояние (private переменные) для каждого объекта наследника отличались? Ладно, буду ещё думать... Добавлено @ 23:27
Хм, ну не знаю... Я хотел подчеркнуть, что одна модель простая - simple - т.е. лёгкая для понимания и модификации со стороны разработчика, а другая - light - лёгкая для браузера. А heavy - это как раз "тяжёлая", сразу интуитивно возникает вопрос - зачем она акая тяжёлая вообще нужна? И дискомфорт даже какой-то смутный... -------------------- |
||||||
|
|||||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
Еще пару ошибок нашел:
- apply init'a не вызывался, потому что в 81 строе вы сами его уничтожаете (но дальше там опять ошибки пошли, после того, как init вызвался - в общем, надо еще смотреть, где там что теряется); - this.constructor.length всегда будет 0 (и что это вообще? когда это свойство будет ставиться?); Да, instanceof в любом случае работает с прототипами конструкторов, а вы его (прототип) подменяете. так я и говорил с легким сарказмом (с легким! ;)), чтобы еще раз сказать, что JS и так-то в 50-200 раз медленней Си и Java в виду своей нынешней ООП-модели и интерпретируемости, а тут он еще медленней становится (ну понятно, что для обеспечения привычного вида инкапсуляции, но я убежден, что в нынешней реализации JS это излишне). Поэтому все-таки это "хэви", но уже в разы оптимизированная (в виду хранения гетторов / сеттеров в одном объекте) "хэви" (что, естественно, радует). Это сообщение отредактировал(а) dsCode - 23.6.2008, 13:15 |
|||
|
||||
Се ля ви |
|
||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Да, надо ещё тестировать, но чесно говоря, уже лень - я альтернативную модель сейчас делаю, с тем, что бы всё-таки заюзать прототипы вместо классов. А эту реализацию развивать смысла нет, потому что instanceof, на мой взгляд, терять нельзя. К тому же действительно новая модель получается более элегантной ![]() Скоро всё будет.
Я написал достаточно подробно про эту фичу: Дело в том, что я этот код пишу не только для демонстрации, но и для copy/paste`а, так что многое может показаться излишним, просто задача решается в общем виде. this.constructor.length - это количество параметров инициализации, передаваемых конструктору (который сейчас выполняется) - у любой функции есть такой метод. В данном случае это - ноль, но если кто-то будет использовать этот код, у него наверняка параметры будут и это не будет ноль, так что ноль вместо этой конструкции я поставить не могу.
Да, "понимание приходит с опытом"... Жаль. Придётся существенно переделывать модель. Но у меня есть ощущение, что она от этого только улучшится и упростится ![]()
Хорошо, убедили. Пускай будет Heavy JavaScript inheritance realization (HJSI) и Light JavaScript inheritance realization (LJSI). ![]() -------------------- |
||||||
|
|||||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
угу, с удовольствием посмотрю (кстати, вот моя старая реализация, имитирующая классовое ООП в JS (с наследованием, тыры-пырами и т.д.). Там есть недочеты, но это старый код (сейчас уже переписан); основные моменты для работы там реализованы (по крайней мере, мне хватало, чтобы сделать систему объектов и связать их. Хотя, если честно, все это тоже накладывает расходы ресурсов). С this.constructor.length я и так все понял до этого, я просто спрашивал - когда он установится? - и метод и свойтво =) а я вот запамятовал )) (мне причудилось, что кол-во аргументов можно только из arguments посмотреть) Это сообщение отредактировал(а) dsCode - 23.6.2008, 14:48 |
|||
|
||||
Се ля ви |
|
||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Итак, представляю вашему вниманию тяжёлую модель реализации наследования. Это не конечная реализация, она нуждается в некотором улучшении и, возможно, дополнении. Но пока она представляет вполне работающий вариант.
В основе лежит следующая схема:
При этом методы хранятся в прототипах, им же передаются privateState`ы от объектов во время выполнения их методов по уже показанному ранее механизму - в этом плане ничего не изменилось, просто вместо явной ссылки _class теперь используется неявная ссылка __proto__. Что же касается объекта-предка, то теперь он доступен только по private ссылке _super у каждого объекта. При этом специальный блок инициализатора объекта (он находится в методе createPrivateState) присваивает ссылки на все его не перекрываемые открытые поля и функции, создаваемому объекту (при этом мы специально передаём ссылки на методы объекту, а не прототипу для того, что бы иметь возможность применять эту модель не только для конструкторов, в которых уже реализована эта модель, но и для любых других - что бы не было необходимости переписывать уже созданный код). К сожалению, модель ещё менее удобна для copy/paste`а - как вы сейчас увидите, в ней в нескольких местах придётся проставлять имя объекта, от которого мы наследуемся и имя самого объекта, а так же, что является старой проблемой, в нескольких местах необходимо дублировать имена private полей. Над этим я сейчас работаю. Итак, пока прошу любить и жаловать:
-------------------- |
||||
|
|||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
И лёгкая модель, с которой работает операция instanceof:
Как видим, результат идентичный кроме строчки вывода 'f1.setPrivateField1 === f2.setPrivateField1 = false', в которой мы чётко видим, что теперь у каждого объекта свои методы, которые при увеличении их количества гораздо быстрее будут забивать всю память, чем просто данные. Тем не менее, эта модель проще и удобнее для написания библиотек руками. В будущем я думаю создать специальный инструментарий как расширение к компрессору (пока первый кандидат на расширение - YUI Compressor, хотя предложения принимаются - для обсуждения этого вопроса создана другая тема), который будет преобразовывать LJSI-конструкторы в HJSI, позволяя разработчику не думать о сложностях реализации HJSI-модели. Ну и, безусловно, время от времени будут вноситься изменения с целью упростить обе модели. Так же на очереди:
![]() -------------------- |
|||
|
||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
Щас времени нет особо, позже напишу.
Се ля ви, я ж саркастически утрировал (писал уже об этом) =)) Зачем такое название? (просто как-то буквально вы это название восприняли) )) Сами говорили:
|
|||
|
||||
dsCode |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
хех =) поначалу хотел спросить, зачем двойное присвоение this.constructor.prototype (строки 15, 16), потом увидел, что первый для ветки if (this.constructor == A) { ... } Есть проблема "холостых выстрелов" (поставьте alert(...) в конструкторе B и создайте один объект - по вашей схеме проалертит три раза, в то время как конструктор должен срабатывать при создании пользовательского объекта (а не вспомогательных того же "класса" внутри реализации библиотеки)):
Вижу (строка 50), что проперти "класса" А копируются в создаваемый объект - т.е. возьмутся не из прототипного объекта (который должен быть экземпляром "класса" А (ну, или wrapper'ом - для избежания "холостых выстрелов")), а будут ownProperty. В общем, сказать, что это перегруженная и сложная для понимания модель - это практически ничего не сказать (уж не обессудьте)! =)) Да я и изначально говорил, что из-за одного спортивного интереса сымитировать концепции Java, так усложнять и напрягать JavaScript не стоит) =)) Это сообщение отредактировал(а) dsCode - 24.6.2008, 23:43 |
||||
|
|||||
Се ля ви |
|
||||||||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Да. Сейчас я немного исправил - я убрал оттуда ссылку на предка и поставил проверку на равенство реально конструктора свойству "constructor" - так по крайней мере не придётся несколько раз упоминать в коде имя конструктора-предка. Но всё равно остаётся проблема, что при copy/paste придётся вписывать имя конструктора в трёх местах, что не очень удобно. При чём, что самое неприятное - от этого не удаётся избавиться даже в лёгкой модели... :( Буду ещё думать.
Почему же, никаких холостых выстрелов! При вызове первый раз конструктор тягается 3 раза.
Да. Этим я как раз и добиваюсь того, что бы у каждого объекта-потомка был свой объект предка и при изменении состояния предка (private-полей) они менялись только для данного объекта, а у остальных таких же объектов объекты предков оказывались бы "не повреждёнными". Этим действием я добиваюсь, что все открытые (интерфейсные) элементы предка получает потомок, но не через прототип, а напрямую. Дело в том, что эта модель наследования должна уметь работать не только с конструкторами, сделанными по ней же, но и с любыми другими альтернативными моделями наследования и даже простыми конструкторами без наследования, где и методы, как и public-поля могут оказаться частью объекта, а не прототипа. По-этому, раз использовать экземпляр предка в качестве прототипа я не могу, мне нужно подтягивать их напрямую ![]() -------------------- |
||||||||||||
|
|||||||||||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Удалось избавиться от упоминаний предка и данного класса во многих местах - теперь и то и другое упоминается лишь в одном месте, таким образом copy/paste`ить стало земетно легче.
Пока не решены проблема с несколькими упоминаниями private-полей и вызовом конструктора из функции с теми параметрами, которые были переданы этой функции (т.е. метод apply для конструктора). -------------------- |
|||
|
||||
АндрейМиндубаев |
|
|||
Новичок Профиль Группа: Участник Сообщений: 5 Регистрация: 14.8.2008 Где: Нижний Новгород Репутация: нет Всего: нет |
Се ля ви, если интересно, то я здесь у себя в блоге написал про свой вариант реализации наследования.
ЗЫЖ Я читал этот форум в своём RSS-Reader-е, эта темка что-то остановилась - и я решил поделится своей разработкой. |
|||
|
||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
АндрейМиндубаев, данная конкретная тема не столько остановилась, сколько довольно-таки естественным путём завершилась, перейдя в новое качество. Дело в том, что мне стала очевидна излишняя громоздкость своей модели наследования и все попытки упростить её носят по сути косметический характер. Так что результатом данного исследования я считаю выработку адекватной модели наследования с использованием всех возможностей инкапсуляции JavaScript, вот только для эффективного использования данной модели на практике нужна одна из трёх вещей: 1. Либо нужно радикальным образом её упростить. 2. Либо нужно создать инструментальные средства, позволяющие упростить разработку с учётом этой модели. 3. Либо нужно создать интерпретатор в JS из другого языка - в моём случае лучше всего подходит Java. В принципе, я сейчас работаю по всем трём направлениям. По первому пути я копаюсь в спеке и изучаю тонкости JS, постоянно думая о том, как их применить для упрощения данной модели. По второму - я, с одной стороны, разбираюсь с проектом YUI Compressor, который хочу приспособить для аналога компиляции JS. С другой стороны, продумываю новые элементы языка, которые можно было бы внести и на стадии такой компиляции превращать в более громоздкие конструкции, примеры которых вы можете видеть в этой теме. И с третьей стороны я ищу open-source редакторы, в которых можно было бы эту функциональность привнести наиболее эффективным образом - с подсветкой, подсказками и прочим. К сожалению, подающий надежды в этом плане SPKet IDE не является open-source проектом... :( Ну и по третьему - уже, в общем-то, есть Google Web Toolkit. Однако, на мой взгляд, он слишком перегружен и я продумываю, как можно было бы легковесно реализовать многие вещи. Вот, например, со дня на день выложу сюда (отдельной темой) свою реализацию emum`ов как в Java - сейчас последние штрихи доделываю. В общем, процесс идёт. Главное - есть интерес к созданию удобного и лаконичного инструментария для создания RIA. А всё остальное - приложится ![]() -------------------- |
|||
|
||||
![]() ![]() ![]() |
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |