Author |
Message |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Sat Mar 01, 2008 9:43 pm (написано за 8 минут 54 секунды)
Post subject:
|
|
Да, точно, весьма досадная ошибка, проклятый копипаст. Но зато теперь практические результаты вполне соответствуют теории: eval в цикле кладет браузеры :) Хотя где жа гарбаж коллектор тогда... В любом случае, голова в пепле, ошибки приняты, раскаиваюсь. Прирост производительности не так уж мал: 40-60%. В случае оперы - 100%. Это при том, что сравниваем мы не с чистым прототипным наследованием, а с какими-то моими накрутками (ну лень мне было выдирать код). Но согласен с тем, что только в очень некоторых приложениях этот код получится самым узким местом. Quote: |
Я добавил в тест вызов родительских методов .run, правда только для моего метода, поскольку не нашёл как у Вас их вызывать. | Как я и сказал, это никак нельзя сделать. В (моей) практике необходимость в этом возникала только для конструкторов, и вот это и было реализовано - как и хотелось, без замыканий. Quote: |
Вот с этого момента поподробнее, пожалуйста. | Я хотел этим сказать, что считаю так: вот такой кодработает быстрее, чем такойНо, как показали тесты, разница все же невелика. Или, может, растет как-нибудь по экспоненте. Может надо бы попробовать десяток методов с десятком замыканий. Примерно на таком вот объекте я и заметил тот значительный прирост, упомянутый мною где-то выше.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Sat Mar 01, 2008 9:56 pm (спустя 13 минут; написано за 3 минуты 50 секунд)
Post subject:
|
|
Quote: |
Тогда на совесть программиста можно оставить и всё остальное =) А людям свойственно ошибаться или просто забывать о требованиях "техники безопасности", или даже не знать про них =) | Разрешите им учиться на своих ошибках, а не программить на всем готовом ;) А если серьезно, то может просто сделать как два таких вот extend'а: копирующий и референсящий. Quote: |
Больше вариантов где замыкания могут поломаться до фактического конструирования класса я придумать не могу. | Я там выше привел такой пример. Да, все можно переделать. Ну так ведь можно вообще объекты "раскатать" в плоский набор функций. Еще раз: вы лишаете человека инструмента. Даже двух: дебаг такого кода очень затруднен. На приведенный мною ранее пример с неизвестной a Сафари выдает такую ошибку: Quote: |
ReferenceError: Can't find variable: a undefined Line: 4 | Фокс третий: Quote: |
Error: a is not defined Source File: file://.../Desktop/WF/wf.html Line: 53 | Строка 53 - это "q.prototype = new clazz;".
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Sat Mar 01, 2008 9:57 pm (спустя 43 секунды)
Post subject:
|
|
Учитывая что мне ещё ни разу не понадобилось делать "настоящее" наследование в проектах, это были просто результаты теоретических изысканий на тему, дабы сделать код более аккуратным =) Насчёт реальных проблем - было бы интересно почитать такое исследование... Да и проверить существующие фреймворки на скорость как генерации классов, так и обращения к родительским методам. Дополнение по синтетическим тестам: по мере роста количества методов мой вариант начинает реально проигрывать, что, в принципе, закономерно. В частности, на func1..12 картина в FF при 10000 итераций WingedFox original: 1.437ms AlexKunin: 0.329ms Надо будет подумать об оптимизации всего этого хозяйства =)
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Sat Mar 01, 2008 9:57 pm (спустя 36 секунд; написано за 57 секунд)
Post subject:
|
|
alexkunin
Каждый использует те инструменты, которые ему подходят =) Как говорили мудрые, "если человеку знаком только молоток, есть все основания полагать что он любую проблему будет решать молотком"
Last edited by WingedFox on Sat Mar 01, 2008 10:00 pm; edited 1 time in total
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Sat Mar 01, 2008 9:59 pm (спустя 1 минуту 43 секунды; написано за 1 минуту 19 секунд)
Post subject:
|
|
WingedFox wrote: |
Дополнение по синтетическим тестам: по мере роста количества методов мой вариант начинает реально проигрывать, что, в принципе, закономерно. В частности, на func1..12 картина в FF при 10000 итераций | Вот-вот, именно для этого и добавлял "мясо". Маловато добавил для ясности картины, как оказалось.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Sat Mar 01, 2008 10:00 pm (спустя 43 секунды; написано за 27 секунд)
Post subject:
|
|
Quote: |
Каждый использует те инструменты, которые ему подходят =) | Согласен. Но дебаг! Не всегда же есть настроение поиграть в оракула.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Sat Mar 01, 2008 10:03 pm (спустя 3 минуты; написано за 1 минуту 48 секунд)
Post subject:
|
|
alexkunin wrote: |
Но дебаг! | Ой, точно... дебаг =) Как много в этом звуке =) Ещё раз - я никого ничего не лишаю. И даже ничего не навязываю. Просто потому, что можно сделать и лучше. PS: Я вообще предпочитаю не использовать такого рода наследование в проектах =)
|
|
Back to top |
|
 |
Rumata
Профессионал

Joined: 17 Aug 2003
Posts: 1850
Карма: 185 поощрить/наказать
|
Posted: Sun Mar 02, 2008 1:16 am (спустя 3 часа 13 минут; написано за 3 минуты 45 секунд)
Post subject:
|
|
alexkunin wrote: |
Вообще же хотелось сравнить с чистым прототипным наследованием, но это ж сколько печатать надо. | а как же чистота эксперимента? очень важен тест и сравнительная таблица ваших вариантов наследования с "чисто прототипным наследованием" в науке всегда сравнивают данные, полученные на основании развитых теорий и их модификаций, с данными из классической теории.
Last edited by Rumata on Sun Mar 02, 2008 7:13 am; edited 1 time in total
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Sun Mar 02, 2008 1:22 am (спустя 5 минут; написано за 1 минуту 15 секунд)
Post subject:
|
|
Rumata wrote: |
очень важен тест и сравнительная таблица ваших вариантов наследования с "чисто прототипным наследованием"? | Вопросительный знак закрался случайно? Классическая теория, т.е. спецификация JS, о производительности мало что говорит, в основном переносит этот вопрос на плечи реализации.
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Sun Mar 02, 2008 12:58 pm (спустя 11 часов 36 минут; написано за 1 минуту 8 секунд)
Post subject:
|
|
WingedFox wrote: |
Больше вариантов где замыкания могут поломаться до фактического конструирования класса я придумать не могу. | Т.е. Вы не предполагаете, что в литерале объекта может попасться функция, ассоциирующаяся с closure?
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 12:08 am (спустя 11 часов 10 минут; написано за 40 секунд)
Post subject:
|
|
AKS
Можно пример?
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Mon Mar 03, 2008 8:14 am (спустя 8 часов 6 минут; написано за 15 секунд)
Post subject:
|
|
Code (JavaScript): | скопировать код в буфер обмена | (new (extend(0, { getReg: function () { var regCache = {}; return function (str) { return regCache[str] || (regCache[str] = new RegExp(str)); }; }() } ) ) ).getReg('a|b'); // => error! |
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 8:42 am (спустя 27 минут; написано за 51 секунду)
Post subject:
|
|
AKS
И как, часто такое встречается в реальной работе? Пример ничем не отличается от того, что я привёл выше.
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Mon Mar 03, 2008 9:19 am (спустя 37 минут; написано за 1 минуту 52 секунды)
Post subject:
|
|
WingedFox wrote: |
И как, часто такое встречается в реальной работе? | Не то, чтобы часто – у некоторых (как писал как-то раз Г.О., уровня для самых маленьких) такое вообще не встречается. Решайте сами, нужно ли это принимать во внимание или нет. Просто если что-то не учтено, то грош тому цена. WingedFox wrote: |
Пример ничем не отличается от того, что я привёл выше. | Что ж, вот Вам отличающийся пример: Code (JavaScript): | скопировать код в буфер обмена | var obj = { a: 10, get b() { return this.a; }, set b(v) { this.a = v; } };
var class1 = extend(0, obj); | Причем этот пример выдаст неожиданный результат во всех скриптах, наивно использующих для реализации вымышленного "наследования" такую технику:Еще что-нибудь? Или достаточно для того, чтобы вникнуть наконец в суть вашей же цитаты о молотке? Вы-то, как человек искушенный , должны понимать, что в первую очередь для работы нужно научиться выбирать нужный инструмент. Тогда не придется плутать в поисках классов там, где их нет, напрасно теряя время на написание бессмысленного кода.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 10:04 am (спустя 44 минуты; написано за 39 секунд)
Post subject:
|
|
WingedFox wrote: |
И как, часто такое встречается в реальной работе? | У меня часто, кстати. Очень удобно. Частный кеш остается частным, до него никак не добраться.
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Mon Mar 03, 2008 10:31 am (спустя 27 минут; написано за 3 минуты 52 секунды)
Post subject:
|
|
alexkunin wrote: |
...до него никак не добраться. | В первую очередь это столь необходимая оптимизация. Мне понравился примерчик (peter.michaux.ca/article/7217) реализации компилятора для поиска элементов по имени, классу, id (поиск на странице LIB.querySelector, а выше идентификатор compile).
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 10:59 am (спустя 27 минут; написано за 5 минут 31 секунду)
Post subject:
|
|
alexkunin
Приватные переменные это замечательная штука, но я говорил не об этом. Подобный подход к созданию методов даёт потенциальную проблему с производительностью, поскольку добавляет лишний слой в стек "локальных контекстов", пробежка по которым в поисках переменных занимает дополнительное время. Quote: |
10.1.4 Scope Chain and Identifier Resolution Every execution context has associated with it a scope chain. A scope chain is a list of objects that are searched when evaluating an Identifier. When control enters an execution context, a scope chain is created and populated with an initial set of objects, depending on the type of code. During execution within an execution context, the scope chain of the execution context is affected only by with statements (section 12.10) and catch clauses (section 12.14). During execution, the syntactic production PrimaryExpression : Identifier is evaluated using the following algorithm: 1. Get the next object in the scope chain. If there isn't one, go to step 5. 2. Call the [[HasProperty]] method of Result(1), passing the Identifier as the property. 3. If Result(2) is true, return a value of type Reference whose base object is Result(1) and whose property name is the Identifier. 4. Go to step 1. 5. Return a value of type Reference whose base object is null and whose property name is the Identifier. |
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 11:05 am (спустя 6 минут; написано за 4 минуты 14 секунд)
Post subject:
|
|
WingedFox wrote: |
Приватные переменные это замечательная штука, но я говорил не об этом. Подобный подход к созданию методов даёт потенциальную проблему с производительностью, поскольку добавляет лишний слой в стек "локальных контекстов", пробежка по которым в поисках переменных занимает дополнительное время. | О, вы тоже заговорили о перфомансе! И тоже слишком рано. Проблема, во первых, потенциальная. А во вторых все тут обсуждаемые примеры так или иначе касаются кеширования, т.е. мы делаем большое увеличение перфоманса за счет его маленького уменьшения. Можно сказать, конечно, что на замыканиях клин светом не сошелся, и можно обойтись без них. Ну, так по большому счету можно обойтись и без наследования (даже прототипного) вообще. P.S. Мне кажется (именно кажется, я не проверял, хотя есть личный опыт таких тормозов), что пачка подряд идущих селекторов (a.b.c.d.func().e) в среднем замедляет веб значительно больше, чем использование замыканий. И не только потому, что замыкания в среднем используются не так широко.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 11:26 am (спустя 20 минут; написано за 13 минут 8 секунд)
Post subject:
|
|
alexkunin
Ну, учитывать его всегда имеет смысл, даже если накладки "потенциальны". С одной стороны - потенциальная тормознутость конструктора, который используется в единичных вызовах, а с другой - перебор контекстов при обращении к "нижележащим" переменным, что может происходить в циклах с критичным временем исполнения. Как всегда - надо оценивать решения до момента их внедрения =) и чётко понимать где могут быть узкие места приложения. alexkunin wrote: |
Можно сказать | Можно, но не нужно =) Любой фреймворк не является панацеей и не предлагает безболезненного и прозрачного перехода к его использованию. В любом случае приходится определять рамки используемых технологий и методик при проектировании чего-либо. На примере моего варианта наследования - это отказ от подобного рода замыканий. alexkunin wrote: |
пачка подряд идущих селекторов (a.b.c.d.func().e) в среднем замедляет веб значительно больше | Ну да. Если написать window.a.b. и далее по тексту, то код будет быстрее, т.к. a становится т.н. "fully qualified identifier" и есть шанс, что его поиск будет вестись сразу от window, а не в соответствии с цитатой из моего предыдущего поста. Тем не менее, рекомендация "кешировать обращения к методам объектов посредством определения локальной переменной" остаётся в силе, поскольку такая цепочка будет вычисляться заново при каждом к ней обращении. Т.е.будет (должно) работать быстрее, чемЯ это давно использую в критичных по скорости циклах, т.ч. в свежих браузерах не тестировал. Возможно что там введены какие-либо кеши, что нивелирует разницу.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 11:42 am (спустя 16 минут; написано за 5 минут 38 секунд)
Post subject:
|
|
WingedFox wrote: |
С одной стороны - потенциальная тормознутость конструктора, который используется в единичных вызовах, а с другой - перебор контекстов при обращении к "нижележащим" переменным, что может происходить в циклах с критичным временем исполнения. Как всегда - надо оценивать решения до момента их внедрения =) и чётко понимать где могут быть узкие места приложения. | Тогда может быть вы не будете добавлять к каждому методу три замыкания? Это даст значительно больший перфоманс хит, чем замыкание в отдельных методах, использующих кеширование. WingedFox wrote: |
Если написать window.a.b. и далее по тексту, то код будет быстрее, т.к. a становится т.н. "fully qualified identifier" и есть шанс, что его поиск будет вестись сразу от window, а не в соответствии с цитатой из моего предыдущего поста. | Это очень частный случай. Обычно this.чтоНибудь встречается значительно чаще window.чтоНибудь, document.чтоНибудь. Но я тут провел тестирование... Возможно, опять ошибся где-то, оттого и такие интересные результаты. Код: Code (JavaScript): | скопировать код в буфер обмена | var N = 100;
function measure(message, func) { var t = new Date().getTime(), i;
for (i = 0; i < N; i++) { func(); }
document.writeln(message + ': ' + ((new Date().getTime() - t) / 1000) + 'ms<br />'); }
(function () {
var a = { b:{ c:{ d:{ e:function () { var i = 1, j = i * 2, k = j / 3; } } } } };
measure('Local var, direct', function () { for (var i = 0; i < 10000; i++) { a.b.c.d.e(); } });
measure('Local var, optimized', function () { for (var i = 0, e = a.b.c.d.e; i < 10000; i++) { e(); } });
}());
var a = { b:{ c:{ d:{ e:function () { var i = 1, j = i * 2, k = j / 3; } } } } };
measure('Global var, direct', function () { for (var i = 0; i < 10000; i++) { a.b.c.d.e(); } });
measure('Global var, optimized', function () { for (var i = 0, e = a.b.c.d.e; i < 10000; i++) { e(); } });
measure('FQI, direct', function () { for (var i = 0; i < 10000; i++) { window.a.b.c.d.e(); } }); | Результаты для Safari 3.0.4:
Local var, direct: 1.958ms Local var, optimized: 1.833ms Global var, direct: 1.973ms Global var, optimized: 1.804ms FQI, direct: 2.209ms Результаты для Firefox 3b3:
Local var, direct: 1.172ms Local var, optimized: 2.325ms Global var, direct: 1.29ms Global var, optimized: 1.922ms FQI, direct: 3.22ms В общем, в самых передовых браузерах FQI не работает. Каким-то чудом промежуточная переменная в фоксе работает почти в два раза медленнее, чем прямое, длинное, скушное имя.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 12:10 pm (спустя 27 минут; написано за 3 минуты 28 секунд)
Post subject:
|
|
alexkunin wrote: |
каждому методу три замыкания | Где 3? Всего 2 - extend и локально создаваемая функция. alexkunin wrote: |
Это даст | Предлагаю утверждения подтверждать кодом =) alexkunin wrote: |
Это очень частный случай. | В некоторых фреймворках не такой уж и частный. В любом случае, получился полный провал предположения. =) Значительно более интересные результаты даёт такое: Code (JavaScript): | скопировать код в буфер обмена | measure('Local/Global var, re-optimized', function () { for (var i = 0, e = a.b.c.d; i < 10000; i++) { e.e(); } }); | IE7: Local var, direct: 0.297ms Local var, optimized: 0.297ms Local var, re-optimized: 0.25ms Global var, direct: 0.297ms Global var, optimized: 0.312ms Global var, re-optimized: 0.235ms FireFox 2.0.0.12 Local var, direct: 0.14ms Local var, optimized: 0.406ms Local var, re-optimized: 0.125ms Global var, direct: 0.329ms Global var, optimized: 0.281ms Global var, re-optimized: 0.125ms
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 12:21 pm (спустя 11 минут; написано за 4 минуты 53 секунды)
Post subject:
|
|
WingedFox wrote: |
Где 3? Всего 2 - extend и локально создаваемая функция. | Говорилось исключительно об этом: WingedFox wrote: |
Предлагаю утверждения подтверждать кодом =) | Я всего лишь основываюсь на ваших словах: "С одной стороны - потенциальная тормознутость конструктора, ...а с другой - перебор контекстов при обращении к "нижележащим" переменным...". Если вы имели в виду перфоманс хит, то сами его и обеспечивайте кодом. Если же другое что-то имели в виду, то весь смысл вашей реплики как (контр)аргумента теряется. WingedFox wrote: |
В некоторых фреймворках не такой уж и частный. В любом случае, получился полный провал предположения. =) | Раз уж фреймворки "некоторые", то случай, в них повсеместный, все равно остается частным. WingedFox wrote: |
В любом случае, получился полный провал предположения. =) | Это да, вообще неинтуитивные результаты. Как, спрошу я вас, можно продолжать пользоваться здравым смыслом? WingedFox wrote: |
Значительно более интересные результаты даёт такое: | А вот это отличный результат. Увы, сам не догадался такое сделать. Зато теперь очевиден универсально самый быстрый (как минимум - не самый медленный) способ. Хоть статью пиши.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 12:43 pm (спустя 21 минуту; написано за 12 минут 35 секунд)
Post subject:
|
|
alexkunin wrote: |
Если вы имели в виду перфоманс хит, то сами его и обеспечивайте кодом. Если же другое что-то имели в виду, то весь смысл вашей реплики как (контр)аргумента теряется. | Я имел в виду то, что при выполнении кодадля доступа к переменной надо будет обработать 4 контекста в поисках идентификатора "переменная". Т.е., теоретически, коддолжен работать быстрее, чем в первом примере. Опять же надо проверять на практике. Поскольку у меня в проектах макс. вложенность поиска 1-2 уровня - никогда не заморачивался этим. alexkunin wrote: |
Это да, вообще неинтуитивные результаты. Как, спрошу я вас, можно продолжать пользоваться здравым смыслом? | Надо посмотреть код и/или пошерстить спеку, как именно вычисляется контекст при обращении к window.variable Вообще, хороший аргумент не использовать window в циклах =) Могу предположить (ещё раз) что основной тормоз идёт из-за того, что при конструировании "variable object" для функции перебирается слишком большое количество свойств всех объектов в цепочке (в т.ч. и дико большого window). Вполне вероятно, что выигрыш от моего варианта получается потому, что явно видно откуда брать this для метода, что уменьшает количество вычислений. Прежде чем писать статью надо убедиться что это адекватно будет работать в других браузерах =)
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Mon Mar 03, 2008 1:17 pm (спустя 34 минуты; написано за 2 минуты 55 секунд)
Post subject:
|
|
alexkunin wrote: |
В общем, в самых передовых браузерах FQI не работает. | У Вас в выражении появился дополнительный оператор точка - соответственно появляются дополнительные вычисления (a VS window.a). WingedFox wrote: |
Надо посмотреть код и/или пошерстить спеку, как именно вычисляется контекст при обращении к window.variable | Идентификатор window, как и любой другой, будет вычисляться в соответствии с цитируемым Вами алгоритмом 10.1.4 (т.е. поиск в scope chain). Затем window.property - 11.2.1 Property Accessors.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 1:22 pm (спустя 4 минуты; написано за 1 минуту 55 секунд)
Post subject:
|
|
AKS wrote: |
У Вас в выражении появился дополнительный оператор точка - соответственно появляются дополнительные вычисления (a VS window.a). | Как я понял, WingedFox именно об этом и говорил: если идем от глобальной переменной (даже от global, в данном случае), то должна бы исключиться фаза поиска. Хотя почему бы, ведь выше по скопу может оказаться своя переменная window. AKS wrote: |
Идентификатор window, как и любой другой, будет вычисляться в соответствии с цитируемым Вами алгоритмом 10.1.4 (т.е. поиск в scope chain). Затем window.property - 11.2.1 Property Accessors. | О, а вот и мое "почему бы" из предыдущего абзаца. Спасибо за разъяснения.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Mon Mar 03, 2008 1:27 pm (спустя 4 минуты; написано за 1 минуту 11 секунд)
Post subject:
|
|
alexkunin
Да, я как-то не обращал внимания, что window может быть "спрятан" под локальной переменной, потому и предположил что имена начинаюшиеся с window будут FQI =) Но вот... облом =)
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Mon Mar 03, 2008 1:32 pm (спустя 5 минут; написано за 26 секунд)
Post subject:
|
|
Да, а я купился на аббревиатуру FQI, отчего подумал, что это не ваше предположение, а где-то вычитанное.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Wed Mar 05, 2008 1:04 am (спустя 1 день 11 часов 32 минуты; написано за 9 минут 46 секунд)
Post subject:
|
|
Вот мне тут подумалось, что вместо такого: Code (JavaScript): | скопировать код в буфер обмена | var Class2 = extend(Class1, { Func1: function() { alert("2.1"); parent.Func1.call(this); }, Func2: function() { alert("2.2"); parent.Func2.call(this); } }); | можно писать так: Code (JavaScript): | скопировать код в буфер обмена | var Class2 = extend(Class1, function (parent) { return { Func1: function() { alert("2.1"); parent.Func1.call(this); }, Func2: function() { alert("2.2"); parent.Func2.call(this); } }}); | Ну и, конечно же, изменить extend соответствующим образом, но это уже тривиально. Плюсы:- все перезамыкания исчезают, и теперь можно спокойно лепить свои замыкания в любых сочетаниях
- дебаг работает как обычно
- все те парсеры (например, jslint), которые рассчитывают на нормальный JS-код, не будут спотыкаться о неизвестную глобальную parent
- избавление от явного и не явного eval, который, как известно, эвил
Минусы:- еще немного более странная форма записи
Кроме того, эту анонимную функцию можно вызывать не один раз во время объявления потомка, а каждый раз в момент создания экземпляра потомка. При этом parent можно сфабриковать таким образом, что вместо такого:можно будет писать так:Опять же, нужны достаточно тривиальные изменения кода extend(). Плюсы:- шугарнее некуда
Минусы:- некоторый перфоманс импакт при достаточно большом количестве экземпляров
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Wed Mar 05, 2008 3:13 am (спустя 2 часа 8 минут; написано за 4 минуты 20 секунд)
Post subject:
|
|
А можно даже так: Code (JavaScript): | скопировать код в буфер обмена | var B = A.extend(function (Super) { return { method1:function (a) { return Super(this).method1(a + 2); } }}); | Super как бы кастует на this прототип на один уровень раньше по цепочке. Опять же, реализация мне кажется тривиальной, причем не нужно трудиться для каждого экземпляра, хотя при этом каждый вызов будет на два дполнительных "пустых" вызова длиннее - Super и обертка над method1. От parent.method1.call(this, a + 2) отличается тем, что кишков таки не видно, ИМХО.
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Fri Mar 07, 2008 1:30 pm (спустя 2 дня 10 часов 17 минут; написано за 5 минут 43 секунды)
Post subject:
|
|
Вот что получилось с Super'ом (в принципе, это готовое решение): Code (JavaScript): | скопировать код в буфер обмена | var Inheritance = { Proto:{ copy:function (prototype) { function BlankConstructor() {} BlankConstructor.prototype = prototype; return new BlankConstructor(); },
wrap:function (prototype) { var wrappers = {}, instance, property;
function wrap(name, func) { wrappers[name] = function () { return func.apply(instance, arguments); }; }
for (property in prototype) { if (typeof prototype[property] === 'function') { wrap(property, prototype[property]); } }
wrap('constructor', prototype.constructor); // IE
return function (that) { instance = that; return wrappers; }; },
inherit:function (prototype, override) { var Parent = prototype.constructor, Child, property;
if (typeof override === 'function') { override = override(Inheritance.Proto.wrap(prototype)); }
Child = override.hasOwnProperty('constructor') ? override.constructor : function () { Parent.apply(this, arguments); };
Child.prototype = Inheritance.Proto.copy(prototype); for (property in override) { if (override.hasOwnProperty(property)) { Child.prototype[property] = override[property]; } } Child.prototype.constructor = Child; // IE Child.prototype.prototype = prototype;
Child.extend = function (override) { return Inheritance.Proto.inherit( this.prototype, override ).constructor; };
return Child.prototype; } },
extend:function (Constructor) { return Inheritance.Proto.inherit(Constructor.prototype, {}).constructor; } }; | И вот пример использования: Code (JavaScript): | скопировать код в буфер обмена | if (!Array.prototype.map) { Array.prototype.map = function (callback) { var result = [], i = 0;
while (i < this.length) { result[i] = callback(this[i], i); i++; }
return result; }; }
function emitTable(rows) { document.write( '<table border="1">' + rows.map(function (cells) { return '<tr>' + cells.map(function (cell) { return '<td>' + cell + '</td>'; }).join('') + '</tr>'; }).join('') + '</table>' ); }
var Base = Inheritance.extend(Object);
var A = Base.extend({ name:null,
constructor:function (name) { this.name = name; document.writeln('------------'); document.writeln('constructing A("' + name + '")'); },
toString:function () { return this.name; },
method:function () { document.writeln('------------'); document.writeln('calling A.prototype.method: name = "' + this.name + '"'); } });
A.toString = function () { return 'A'; };
var B = A.extend(function (Super) { return { constructor:function (name) { Super(this).constructor(name); document.writeln('constructing B("' + name + '")'); },
method:function () { Super(this).method(); document.writeln('calling B.prototype.method: name = "' + this.name + '"'); } }});
B.toString = function () { return 'B'; };
var C = B.extend(function (Super) { return { constructor:function (name) { Super(this).constructor(name); document.writeln('constructing C("' + name + '")'); },
method:function () { Super(this).method(); document.writeln('calling C.prototype.method: name = "' + this.name + '"'); } }});
C.toString = function () { return 'C'; };
var D = C.extend(function (Super) { return { constructor:function (name) { Super(this).constructor(name); document.writeln('constructing D("' + name + '")'); },
method:function () { Super(this).method(); document.writeln('calling D.prototype.method: name = "' + this.name + '"'); } }; });
D.toString = function () { return 'D'; };
document.write('<h3>instantinating</h3>');
var a = new A('a'); var b = new B('b'); var c = new C('c'); var d = new D('d');
document.write('<h3>calling method</h3>');
a.method(); b.method(); c.method(); d.method();
document.write('<h3>checking prototype chains</h3>');
emitTable([ [ 'a:', a.constructor ], [ 'b:', b.constructor, b.prototype.constructor ], [ 'c:', c.constructor, c.prototype.constructor, c.prototype.prototype.constructor ], [ 'd:', d.constructor, d.prototype.constructor, d.prototype.prototype.constructor, d.prototype.prototype.prototype.constructor ], [ 'A:', A ], [ 'B:', B, B.prototype.prototype.constructor ], [ 'C:', C, C.prototype.prototype.constructor, C.prototype.prototype.prototype.constructor ], [ 'D:', D, D.prototype.prototype.constructor, D.prototype.prototype.prototype.constructor, D.prototype.prototype.prototype.prototype.constructor ] ]);
var constructors = [ A, B, C, D ]; var instances = [ a, b, c, d ];
document.write('<h3>checking instanceof</h3>');
emitTable( [ [ '' ].concat(instances) ].concat( constructors.map(function (constructor) { return [ constructor ].concat(instances.map(function (instance) { return instance instanceof constructor ? 'Y' : '-'; })); }) ) ); | И результат работы примера: Code (any language): | скопировать код в буфер обмена | instantinating ------------ constructing A("a") ------------ constructing A("b") constructing B("b") ------------ constructing A("c") constructing B("c") constructing C("c") ------------ constructing A("d") constructing B("d") constructing C("d") constructing D("d")
calling method ------------ calling A.prototype.method: name = "a" ------------ calling A.prototype.method: name = "b" calling B.prototype.method: name = "b" ------------ calling A.prototype.method: name = "c" calling B.prototype.method: name = "c" calling C.prototype.method: name = "c" ------------ calling A.prototype.method: name = "d" calling B.prototype.method: name = "d" calling C.prototype.method: name = "d" calling D.prototype.method: name = "d"
checking prototype chains a: A b: B A c: C B A d: D C B A A: A B: B A C: C B A D: D C B A
checking instanceof a b c d A Y Y Y Y B - Y Y Y C - - Y Y D - - - Y | Если какой-нибудь промежуточный класс "занулить" таким вот образом:То ничего не поламается: Code (any language): | скопировать код в буфер обмена | instantinating ------------ constructing A("a") ------------ constructing A("b") ------------ constructing A("c") constructing C("c") ------------ constructing A("d") constructing C("d") constructing D("d")
calling method ------------ calling A.prototype.method: name = "a" ------------ calling A.prototype.method: name = "b" ------------ calling A.prototype.method: name = "c" calling C.prototype.method: name = "c" ------------ calling A.prototype.method: name = "d" calling C.prototype.method: name = "d" calling D.prototype.method: name = "d"
checking prototype chains a: A b: B A c: C B A d: D C B A A: A B: B A C: C B A D: D C B A
checking instanceof a b c d A Y Y Y Y B - Y Y Y C - - Y Y D - - - Y | Вообще prototype.prototype для работы наследования не нужен. Это просто бикоз ай кэн. Можно очень просто пере/до-писать на "parent.method()" вместо "Super(this).method()".
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Fri Mar 07, 2008 2:16 pm (спустя 45 минут; написано за 41 секунду)
Post subject:
|
|
alexkunin
Можете это вариант в тест на скорость добавить?
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Fri Mar 07, 2008 2:33 pm (спустя 17 минут; написано за 23 секунды)
Post subject:
|
|
Предоставляю эту честь вам ;) С меня хватило того, что я сам вариант реализовал :))
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Fri Mar 07, 2008 2:38 pm (спустя 4 минуты; написано за 40 секунд)
Post subject:
|
|
alexkunin
Ага, спасибо. Если руки дойдут - сделаю. Только не знаю, когда это случится.
|
|
Back to top |
|
 |
Rumata
Профессионал

Joined: 17 Aug 2003
Posts: 1850
Карма: 185 поощрить/наказать
|
Posted: Fri Mar 07, 2008 4:29 pm (спустя 1 час 51 минуту; написано за 41 секунду)
Post subject:
|
|
 М |
| вам не надоело толочь воду в ступе? |
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Fri Mar 07, 2008 4:34 pm (спустя 4 минуты; написано за 39 секунд)
Post subject:
|
|
Rumata
Ничуть. Это очень полезное занятие, особенно когда используются хорошие заклинания =)
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Fri Mar 07, 2008 4:35 pm (спустя 1 минуту 53 секунды; написано за 2 минуты 55 секунд)
Post subject:
|
|
Rumata, в чем эта водотолкотня выражается? Была идея, поправили ошибки, предложили варианты получше, избавились от недостатков, получили рабочий код. Не вижу проблем. Если они есть, то укажите, пожалуйста. Еще бы Zeroglif'а сюда - расчехлил бы все мутные моменты враз. Еще больше пользы было бы.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Fri Mar 07, 2008 4:48 pm (спустя 12 минут; написано за 45 секунд)
Post subject:
|
|
Как ни странно, время нашлось даже сегодня =) IE7
WingedFox original: 0.78ms AlexKunin 1: 0.625ms AlexKunin 2: 0.78ms FF 2.0.0.12
WingedFox original: 0.89ms AlexKunin 1: 0.468ms AlexKunin 2: 0.828ms
Description: |
|
 Download |
Filename: |
wf1.zip |
Filesize: |
3.55 KB |
Downloaded: |
593 Time(s) |
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Fri Mar 07, 2008 4:52 pm (спустя 4 минуты; написано за 1 минуту 20 секунд)
Post subject:
|
|
Нужно будет расширить тесты: мало/много методов, короткое/длинное (глубокое) наследование. А то и правда цифры не показательны, не понятно что выигрывается и проигрывается в каждом конкретном случае.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 269 поощрить/наказать
Location: Питер
|
Posted: Fri Mar 07, 2008 4:54 pm (спустя 2 минуты; написано за 59 секунд)
Post subject:
|
|
Сейчас проводится тестирование скорости конструирования объекта с 14 методами (func1..12, run, constructor). А вообще, бессмысленное это занятие =)
|
|
Back to top |
|
 |
alexkunin
Участник форума
Joined: 25 Feb 2006
Posts: 113
Карма: 11 поощрить/наказать
|
Posted: Fri Mar 07, 2008 4:59 pm (спустя 4 минуты; написано за 2 минуты 57 секунд)
Post subject:
|
|
Quote: |
Сейчас проводится тестирование скорости конструирования объекта с 14 методами (func1..12, run, constructor). | Да, я заметил. Хотелось бы замерять отдельно потери на наследование, на создание экземпляров, на Super-вызовы. Quote: |
А вообще, бессмысленное это занятие =) | И вы с Rumata? Лично я собираюсь использовать этот код. Предыдущий мой код тоже не с потолка взят, а из проекта с довольно широкой и достаточно глубокой иерархией. Как раз настолько широкой и глубокой, что пришлось подумать о более удобных (компактных) вариантах записи наследования и вызовов.
|
|
Back to top |
|
 |
|