Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

yaji - ещё один вариант наследования (WingedFox, оценка: 1)
Goto page Previous  1, 2, 3  Next
Author Message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Sat Mar 01, 2008 9:43 pm (написано за 8 минут 54 секунды)
   Post subject:
Reply with quote

Да, точно, весьма досадная ошибка, проклятый копипаст. Но зато теперь практические результаты вполне соответствуют теории: eval в цикле кладет браузеры :) Хотя где жа гарбаж коллектор тогда... В любом случае, голова в пепле, ошибки приняты, раскаиваюсь.

Прирост производительности не так уж мал: 40-60%. В случае оперы - 100%. Это при том, что сравниваем мы не с чистым прототипным наследованием, а с какими-то моими накрутками (ну лень мне было выдирать код). Но согласен с тем, что только в очень некоторых приложениях этот код получится самым узким местом.
Quote:
Я добавил в тест вызов родительских методов .run, правда только для моего метода, поскольку не нашёл как у Вас их вызывать.
Как я и сказал, это никак нельзя сделать. В (моей) практике необходимость в этом возникала только для конструкторов, и вот это и было реализовано - как и хотелось, без замыканий.
Quote:
Вот с этого момента поподробнее, пожалуйста.
Я хотел этим сказать, что считаю так: вот такой код
Code (JavaScript): скопировать код в буфер обмена
new function () {
    var closure1, closure2, ...
    //
}
работает быстрее, чем такой
Code (JavaScript): скопировать код в буфер обмена
new function () {
    var closure1, closure2, ...
    // 10 - 20 строк кода
}
Но, как показали тесты, разница все же невелика. Или, может, растет как-нибудь по экспоненте. Может надо бы попробовать десяток методов с десятком замыканий. Примерно на таком вот объекте я и заметил тот значительный прирост, упомянутый мною где-то выше.
Back to top
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Sat Mar 01, 2008 9:56 pm (спустя 13 минут; написано за 3 минуты 50 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Sat Mar 01, 2008 9:57 pm (спустя 43 секунды)
   Post subject:
Reply with quote

Учитывая что мне ещё ни разу не понадобилось делать "настоящее" наследование в проектах, это были просто результаты теоретических изысканий на тему, дабы сделать код более аккуратным =)
Насчёт реальных проблем - было бы интересно почитать такое исследование... Да и проверить существующие фреймворки на скорость как генерации классов, так и обращения к родительским методам.

Дополнение по синтетическим тестам:
по мере роста количества методов мой вариант начинает реально проигрывать, что, в принципе, закономерно.
В частности, на func1..12 картина в FF при 10000 итераций

WingedFox original: 1.437ms
AlexKunin: 0.329ms

Надо будет подумать об оптимизации всего этого хозяйства =)
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Sat Mar 01, 2008 9:57 pm (спустя 36 секунд; написано за 57 секунд)
   Post subject:
Reply with quote

alexkunin
Каждый использует те инструменты, которые ему подходят =)
Как говорили мудрые, "если человеку знаком только молоток, есть все основания полагать что он любую проблему будет решать молотком"

Last edited by WingedFox on Sat Mar 01, 2008 10:00 pm; edited 1 time in total
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Sat Mar 01, 2008 9:59 pm (спустя 1 минуту 43 секунды; написано за 1 минуту 19 секунд)
   Post subject:
Reply with quote

WingedFox wrote:
Дополнение по синтетическим тестам:
по мере роста количества методов мой вариант начинает реально проигрывать, что, в принципе, закономерно.
В частности, на func1..12 картина в FF при 10000 итераций
Вот-вот, именно для этого и добавлял "мясо". Маловато добавил для ясности картины, как оказалось.
Back to top
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Sat Mar 01, 2008 10:00 pm (спустя 43 секунды; написано за 27 секунд)
   Post subject:
Reply with quote

Quote:
Каждый использует те инструменты, которые ему подходят =)
Согласен. Но дебаг! Не всегда же есть настроение поиграть в оракула.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Sat Mar 01, 2008 10:03 pm (спустя 3 минуты; написано за 1 минуту 48 секунд)
   Post subject:
Reply with quote

alexkunin wrote:
Но дебаг!
Ой, точно... дебаг =) Как много в этом звуке =)
Ещё раз - я никого ничего не лишаю.
И даже ничего не навязываю. Просто потому, что можно сделать и лучше.

PS: Я вообще предпочитаю не использовать такого рода наследование в проектах =)
Back to top
View user's profile Send private message
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Sun Mar 02, 2008 1:16 am (спустя 3 часа 13 минут; написано за 3 минуты 45 секунд)
   Post subject:
Reply with quote

alexkunin wrote:
Вообще же хотелось сравнить с чистым прототипным наследованием, но это ж сколько печатать надо.
а как же чистота эксперимента?
очень важен тест и сравнительная таблица ваших вариантов наследования с "чисто прототипным наследованием"
в науке всегда сравнивают данные, полученные на основании развитых теорий и их модификаций, с данными из классической теории.

Last edited by Rumata on Sun Mar 02, 2008 7:13 am; edited 1 time in total
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Sun Mar 02, 2008 1:22 am (спустя 5 минут; написано за 1 минуту 15 секунд)
   Post subject:
Reply with quote

Rumata wrote:
очень важен тест и сравнительная таблица ваших вариантов наследования с "чисто прототипным наследованием"?
Вопросительный знак закрался случайно?

Классическая теория, т.е. спецификация JS, о производительности мало что говорит, в основном переносит этот вопрос на плечи реализации.
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Mar 02, 2008 12:58 pm (спустя 11 часов 36 минут; написано за 1 минуту 8 секунд)
   Post subject:
Reply with quote

WingedFox wrote:
Больше вариантов где замыкания могут поломаться до фактического конструирования класса я придумать не могу.
Т.е. Вы не предполагаете, что в литерале объекта может попасться функция, ассоциирующаяся с closure?
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 12:08 am (спустя 11 часов 10 минут; написано за 40 секунд)
   Post subject:
Reply with quote

AKS
Можно пример?
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 8:14 am (спустя 8 часов 6 минут; написано за 15 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 8:42 am (спустя 27 минут; написано за 51 секунду)
   Post subject:
Reply with quote

AKS
И как, часто такое встречается в реальной работе?

Пример ничем не отличается от того, что я привёл выше.
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 9:19 am (спустя 37 минут; написано за 1 минуту 52 секунды)
   Post subject:
Reply with quote

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);
Причем этот пример выдаст неожиданный результат во всех скриптах, наивно использующих для реализации вымышленного "наследования" такую технику:
Code (JavaScript): скопировать код в буфер обмена
for (var i in obj) newObj[i] = obj[i];
Еще что-нибудь? Или достаточно для того, чтобы вникнуть наконец в суть вашей же цитаты о молотке?
Вы-то, как человек искушенный , должны понимать, что в первую очередь для работы нужно научиться выбирать нужный инструмент. Тогда не придется плутать в поисках классов там, где их нет, напрасно теряя время на написание бессмысленного кода.
Back to top
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 10:04 am (спустя 44 минуты; написано за 39 секунд)
   Post subject:
Reply with quote

WingedFox wrote:
И как, часто такое встречается в реальной работе?
У меня часто, кстати. Очень удобно. Частный кеш остается частным, до него никак не добраться.
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 10:31 am (спустя 27 минут; написано за 3 минуты 52 секунды)
   Post subject:
Reply with quote

alexkunin wrote:
...до него никак не добраться.
В первую очередь это столь необходимая оптимизация.
Мне понравился примерчик (peter.michaux.ca/article/7217) реализации компилятора для поиска элементов по имени, классу, id (поиск на странице LIB.querySelector, а выше идентификатор compile).
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 10:59 am (спустя 27 минут; написано за 5 минут 31 секунду)
   Post subject:
Reply with quote

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
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 11:05 am (спустя 6 минут; написано за 4 минуты 14 секунд)
   Post subject:
Reply with quote

WingedFox wrote:
Приватные переменные это замечательная штука, но я говорил не об этом.

Подобный подход к созданию методов даёт потенциальную проблему с производительностью, поскольку добавляет лишний слой в стек "локальных контекстов", пробежка по которым в поисках переменных занимает дополнительное время.
О, вы тоже заговорили о перфомансе! И тоже слишком рано. Проблема, во первых, потенциальная. А во вторых все тут обсуждаемые примеры так или иначе касаются кеширования, т.е. мы делаем большое увеличение перфоманса за счет его маленького уменьшения.

Можно сказать, конечно, что на замыканиях клин светом не сошелся, и можно обойтись без них. Ну, так по большому счету можно обойтись и без наследования (даже прототипного) вообще.

P.S. Мне кажется (именно кажется, я не проверял, хотя есть личный опыт таких тормозов), что пачка подряд идущих селекторов (a.b.c.d.func().e) в среднем замедляет веб значительно больше, чем использование замыканий. И не только потому, что замыкания в среднем используются не так широко.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 11:26 am (спустя 20 минут; написано за 13 минут 8 секунд)
   Post subject:
Reply with quote

alexkunin
Ну, учитывать его всегда имеет смысл, даже если накладки "потенциальны".
С одной стороны - потенциальная тормознутость конструктора, который используется в единичных вызовах, а с другой - перебор контекстов при обращении к "нижележащим" переменным, что может происходить в циклах с критичным временем исполнения.
Как всегда - надо оценивать решения до момента их внедрения =) и чётко понимать где могут быть узкие места приложения.
alexkunin wrote:
Можно сказать
Можно, но не нужно =)
Любой фреймворк не является панацеей и не предлагает безболезненного и прозрачного перехода к его использованию.
В любом случае приходится определять рамки используемых технологий и методик при проектировании чего-либо.
На примере моего варианта наследования - это отказ от подобного рода замыканий.
alexkunin wrote:
пачка подряд идущих селекторов (a.b.c.d.func().e) в среднем замедляет веб значительно больше
Ну да.
Если написать window.a.b. и далее по тексту, то код будет быстрее, т.к. a становится т.н. "fully qualified identifier" и есть шанс, что его поиск будет вестись сразу от window, а не в соответствии с цитатой из моего предыдущего поста.
Тем не менее, рекомендация "кешировать обращения к методам объектов посредством определения локальной переменной" остаётся в силе, поскольку такая цепочка будет вычисляться заново при каждом к ней обращении.

Т.е.
Code (JavaScript): скопировать код в буфер обмена
for (var i=0,method=a.b.c.d.e.f.g;i<10000;i++) {
    method();
}
будет (должно) работать быстрее, чем
Code (JavaScript): скопировать код в буфер обмена
for (var i=0;i<10000;i++) {
    a.b.c.d.e.f.g();
}
Я это давно использую в критичных по скорости циклах, т.ч. в свежих браузерах не тестировал. Возможно что там введены какие-либо кеши, что нивелирует разницу.
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 11:42 am (спустя 16 минут; написано за 5 минут 38 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 12:10 pm (спустя 27 минут; написано за 3 минуты 28 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 12:21 pm (спустя 11 минут; написано за 4 минуты 53 секунды)
   Post subject:
Reply with quote

WingedFox wrote:
Где 3?
Всего 2 - extend и локально создаваемая функция.
Говорилось исключительно об этом:
Code (JavaScript): скопировать код в буфер обмена
var clazz = arguments.callee, parent = arguments.callee.parent, self = this;
WingedFox wrote:
Предлагаю утверждения подтверждать кодом =)
Я всего лишь основываюсь на ваших словах: "С одной стороны - потенциальная тормознутость конструктора, ...а с другой - перебор контекстов при обращении к "нижележащим" переменным...". Если вы имели в виду перфоманс хит, то сами его и обеспечивайте кодом. Если же другое что-то имели в виду, то весь смысл вашей реплики как (контр)аргумента теряется.
WingedFox wrote:
В некоторых фреймворках не такой уж и частный. В любом случае, получился полный провал предположения. =)
Раз уж фреймворки "некоторые", то случай, в них повсеместный, все равно остается частным.
WingedFox wrote:
В любом случае, получился полный провал предположения. =)
Это да, вообще неинтуитивные результаты. Как, спрошу я вас, можно продолжать пользоваться здравым смыслом?
WingedFox wrote:
Значительно более интересные результаты даёт такое:
А вот это отличный результат. Увы, сам не догадался такое сделать. Зато теперь очевиден универсально самый быстрый (как минимум - не самый медленный) способ. Хоть статью пиши.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 12:43 pm (спустя 21 минуту; написано за 12 минут 35 секунд)
   Post subject:
Reply with quote

alexkunin wrote:
Если вы имели в виду перфоманс хит, то сами его и обеспечивайте кодом. Если же другое что-то имели в виду, то весь смысл вашей реплики как (контр)аргумента теряется.
Я имел в виду то, что при выполнении кода
Code (any language): скопировать код в буфер обмена
для доступа к переменной надо будет обработать 4 контекста в поисках идентификатора "переменная".
Т.е., теоретически, код
Code (any language): скопировать код в буфер обмена
должен работать быстрее, чем в первом примере.
Опять же надо проверять на практике. Поскольку у меня в проектах макс. вложенность поиска 1-2 уровня - никогда не заморачивался этим.
alexkunin wrote:
Это да, вообще неинтуитивные результаты. Как, спрошу я вас, можно продолжать пользоваться здравым смыслом?
Надо посмотреть код и/или пошерстить спеку, как именно вычисляется контекст при обращении к window.variable
Вообще, хороший аргумент не использовать window в циклах =)
Могу предположить (ещё раз) что основной тормоз идёт из-за того, что при конструировании "variable object" для функции перебирается слишком большое количество свойств всех объектов в цепочке (в т.ч. и дико большого window).

Вполне вероятно, что выигрыш от моего варианта получается потому, что явно видно откуда брать this для метода, что уменьшает количество вычислений.
Прежде чем писать статью надо убедиться что это адекватно будет работать в других браузерах =)
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 1:17 pm (спустя 34 минуты; написано за 2 минуты 55 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 1:22 pm (спустя 4 минуты; написано за 1 минуту 55 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Mon Mar 03, 2008 1:27 pm (спустя 4 минуты; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

alexkunin
Да, я как-то не обращал внимания, что window может быть "спрятан" под локальной переменной, потому и предположил что имена начинаюшиеся с window будут FQI =)
Но вот... облом =)
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 1:32 pm (спустя 5 минут; написано за 26 секунд)
   Post subject:
Reply with quote

Да, а я купился на аббревиатуру FQI, отчего подумал, что это не ваше предположение, а где-то вычитанное.
Back to top
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Wed Mar 05, 2008 1:04 am (спустя 1 день 11 часов 32 минуты; написано за 9 минут 46 секунд)
   Post subject:
Reply with quote

Вот мне тут подумалось, что вместо такого:
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 соответствующим образом, но это уже тривиально.

Плюсы:
  1. все перезамыкания исчезают, и теперь можно спокойно лепить свои замыкания в любых сочетаниях
  2. дебаг работает как обычно
  3. все те парсеры (например, jslint), которые рассчитывают на нормальный JS-код, не будут спотыкаться о неизвестную глобальную parent
  4. избавление от явного и не явного eval, который, как известно, эвил
Минусы:
  1. еще немного более странная форма записи
Кроме того, эту анонимную функцию можно вызывать не один раз во время объявления потомка, а каждый раз в момент создания экземпляра потомка. При этом parent можно сфабриковать таким образом, что вместо такого:
Code (JavaScript): скопировать код в буфер обмена
parent.Func1.call(this);
можно будет писать так:
Code (JavaScript): скопировать код в буфер обмена
parent.Func1();
Опять же, нужны достаточно тривиальные изменения кода extend().

Плюсы:
  1. шугарнее некуда
Минусы:
  1. некоторый перфоманс импакт при достаточно большом количестве экземпляров
Back to top
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Wed Mar 05, 2008 3:13 am (спустя 2 часа 8 минут; написано за 4 минуты 20 секунд)
   Post subject:
Reply with quote

А можно даже так:
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
View user's profile Send private message Send e-mail
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 1:30 pm (спустя 2 дня 10 часов 17 минут; написано за 5 минут 43 секунды)
   Post subject:
Reply with quote

Вот что получилось с 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 (JavaScript): скопировать код в буфер обмена
var B = A.extend({});
То ничего не поламается:
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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Fri Mar 07, 2008 2:16 pm (спустя 45 минут; написано за 41 секунду)
   Post subject:
Reply with quote

alexkunin
Можете это вариант в тест на скорость добавить?
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 2:33 pm (спустя 17 минут; написано за 23 секунды)
   Post subject:
Reply with quote

Предоставляю эту честь вам ;) С меня хватило того, что я сам вариант реализовал :))
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Fri Mar 07, 2008 2:38 pm (спустя 4 минуты; написано за 40 секунд)
   Post subject:
Reply with quote

alexkunin
Ага, спасибо. Если руки дойдут - сделаю. Только не знаю, когда это случится.
Back to top
View user's profile Send private message
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 4:29 pm (спустя 1 час 51 минуту; написано за 41 секунду)
   Post subject:
Reply with quote


М

вам не надоело толочь воду в ступе?
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Fri Mar 07, 2008 4:34 pm (спустя 4 минуты; написано за 39 секунд)
   Post subject:
Reply with quote

Rumata
Ничуть. Это очень полезное занятие, особенно когда используются хорошие заклинания =)
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 4:35 pm (спустя 1 минуту 53 секунды; написано за 2 минуты 55 секунд)
   Post subject:
Reply with quote

Rumata, в чем эта водотолкотня выражается? Была идея, поправили ошибки, предложили варианты получше, избавились от недостатков, получили рабочий код. Не вижу проблем. Если они есть, то укажите, пожалуйста.

Еще бы Zeroglif'а сюда - расчехлил бы все мутные моменты враз. Еще больше пользы было бы.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Fri Mar 07, 2008 4:48 pm (спустя 12 минут; написано за 45 секунд)
   Post subject:
Reply with quote

Как ни странно, время нашлось даже сегодня =)

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


wf1.zip
 Description:
Ещё немного тестов

Download
 Filename:  wf1.zip
 Filesize:  3.55 KB
 Downloaded:  570 Time(s)

Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 4:52 pm (спустя 4 минуты; написано за 1 минуту 20 секунд)
   Post subject:
Reply with quote

Нужно будет расширить тесты: мало/много методов, короткое/длинное (глубокое) наследование. А то и правда цифры не показательны, не понятно что выигрывается и проигрывается в каждом конкретном случае.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 269
   поощрить/наказать

Location: Питер

PostPosted: Fri Mar 07, 2008 4:54 pm (спустя 2 минуты; написано за 59 секунд)
   Post subject:
Reply with quote

Сейчас проводится тестирование скорости конструирования объекта с 14 методами (func1..12, run, constructor).

А вообще, бессмысленное это занятие =)
Back to top
View user's profile Send private message
alexkunin
Участник форума



Joined: 25 Feb 2006
Posts: 113
Карма: 11
   поощрить/наказать


PostPosted: Fri Mar 07, 2008 4:59 pm (спустя 4 минуты; написано за 2 минуты 57 секунд)
   Post subject:
Reply with quote

Quote:
Сейчас проводится тестирование скорости конструирования объекта с 14 методами (func1..12, run, constructor).
Да, я заметил. Хотелось бы замерять отдельно потери на наследование, на создание экземпляров, на Super-вызовы.
Quote:
А вообще, бессмысленное это занятие =)
И вы с Rumata?

Лично я собираюсь использовать этот код. Предыдущий мой код тоже не с потолка взят, а из проекта с довольно широкой и достаточно глубокой иерархией. Как раз настолько широкой и глубокой, что пришлось подумать о более удобных (компактных) вариантах записи наследования и вызовов.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML