Comments 9
Здесь мы экономим ресурсы за счёт того, что создаваемая каждый раз в конструкторе функция состоит всего из одной строки — вызова настоящего тела метода.
Весьма странное понимание проблемы. Код функций никогда не копируется, поэтому от их размера ничего не зависит. Повышенное потребление памяти связано с тем, что каждый экземпляр функции хранит свое окружение (closure), т.е. ссылки на переменные из внешних областей видимости.
В данном же случае хранение ссылок на переменные заменяется копированием методов приватного объекта в публичный, что сравнимо по объему. Так что весьма сомнительно, что это даст какой-нибудь выигрыш. Тесты прогоняли?
> Код функций никогда не копируется, поэтому от их размера ничего не зависит.
Зависит от типа функции. Стандарт предусматривает оптимизацию в виде объединённых объектов, но там должны соблюдаться определённые условия. Новая версия стандарта (ECMA-262-5, текущий драфт) определяет внутреннее свойство [[Code]], которое может реюзаться между (объединёнными) функциями, но в текущей версии стандарта об этом ничего не сказано (хотя, на практике, я думаю, реализации делают оптимизацию, включая предложенную с объединёнными объектами). Но, повторю, зависит это от типа функций. Разбирал это в пятой части статей об ECMAscript.
Зависит от типа функции. Стандарт предусматривает оптимизацию в виде объединённых объектов, но там должны соблюдаться определённые условия. Новая версия стандарта (ECMA-262-5, текущий драфт) определяет внутреннее свойство [[Code]], которое может реюзаться между (объединёнными) функциями, но в текущей версии стандарта об этом ничего не сказано (хотя, на практике, я думаю, реализации делают оптимизацию, включая предложенную с объединёнными объектами). Но, повторю, зависит это от типа функций. Разбирал это в пятой части статей об ECMAscript.
kriomant, в принципе вы правы, создаётся новое замыкание (а дублирование кода действительно зависит от браузера). Но я, очевидно, немного неверно сформулировал мысль: обратите внимание, что все private-методы выносятся за пределы определения класса, и, следовательно, сам класс о них ничего не знает и никак их не дублирует — а как правило таких методов больше, чем публичных, работающих с ними (это уже просто практика), которые и создаются в конструкторе. Тесты показывают, что выигрыш действительно есть — где-то в 1,8 раза (например, 0,768 против 0,454 для создания 1000 объектов с 1000-ей закрытых и 1000-й открытых методов).
А вот с приведённым решением с сервером объектов, ради которого статья и затевалась, получается интереснее — это решение работает приблизительно в 7 раз быстрее во всех браузерах, кроме Firefox (там медленнее)… но только при первом прогоне — потом (при обновлении страницы) и лис прекрасно обрабатывает его.
Такая вот получается картина.
А вот с приведённым решением с сервером объектов, ради которого статья и затевалась, получается интереснее — это решение работает приблизительно в 7 раз быстрее во всех браузерах, кроме Firefox (там медленнее)… но только при первом прогоне — потом (при обновлении страницы) и лис прекрасно обрабатывает его.
Такая вот получается картина.
Интересное решение, своеобразное ;). А какова основная цель? Публичные (external) свойства копируются, что увеличивает расход ресурсов.
> if(objects[_id].Eexternal
Опечатка.
> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)
Ну блин, ещё бы, совершенно новый независимый объект Number создаётся, никак не связанный с данной обёрткой (не имеющий расширенных, скопированных свойств) ;)
В целом, не считая недочётов, что extenral stuff копируется в каждый новый объект, а не наследуется, а также, не считая того, что в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs» и обратиться к нужному «скрытому» объекту, — идея своеобразно-интересная ;)
P.S.: немного затрагивал тему инкапсуляции (с позиции восприятия) в седьмой части статей об ECMAscript.
> if(objects[_id].Eexternal
Опечатка.
> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)
Ну блин, ещё бы, совершенно новый независимый объект Number создаётся, никак не связанный с данной обёрткой (не имеющий расширенных, скопированных свойств) ;)
В целом, не считая недочётов, что extenral stuff копируется в каждый новый объект, а не наследуется, а также, не считая того, что в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs» и обратиться к нужному «скрытому» объекту, — идея своеобразно-интересная ;)
P.S.: немного затрагивал тему инкапсуляции (с позиции восприятия) в седьмой части статей об ECMAscript.
> Ну блин, ещё бы, совершенно новый независимый объект Number
На самом деле индексом в массиве объектов является примитив, так что проверка нужна.
> extenral stuff копируется в каждый новый объект, а не наследуется
Я сейчас как раз ищу решение, как его унаследовать. :^) Это, я надеюсь, позволит избавиться от перерасхода ресурсов и от тормозов в лисе при первом прогоне. Спасибо за совет.
> в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs»
А как? Чесслово, интересно. Может, это позволит сделать что-нибудь интересное. :^)
На самом деле индексом в массиве объектов является примитив, так что проверка нужна.
> extenral stuff копируется в каждый новый объект, а не наследуется
Я сейчас как раз ищу решение, как его унаследовать. :^) Это, я надеюсь, позволит избавиться от перерасхода ресурсов и от тормозов в лисе при первом прогоне. Спасибо за совет.
> в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs»
А как? Чесслово, интересно. Может, это позволит сделать что-нибудь интересное. :^)
> На самом деле индексом в массиве объектов является примитив, так что проверка нужна.
Да нет, я имею в виду, Вы пишите:
И так понятно, что «object2» теперь совершенно независимый (новый) объект и у него нет никакого метода «publicMethod», зачем писать про то, что «сервер откажет», если object2 никак не связан с сервером?
Ну и (просто для справки) — ключами объекта (включая массивы) являются всегда строки, т.е. не просто примитив, а именно примитив-строка.
> А как? Чесслово, интересно
Например, в Spidermonkey до версии 1.7, eval-у можно передать вызывающий контекст, тем самым получая доступ к внутреннему объекту переменных.
Да нет, я имею в виду, Вы пишите:
# object2 = new Number(object2 * 1);
# object2.publicMethod();
…
И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)
И так понятно, что «object2» теперь совершенно независимый (новый) объект и у него нет никакого метода «publicMethod», зачем писать про то, что «сервер откажет», если object2 никак не связан с сервером?
Ну и (просто для справки) — ключами объекта (включая массивы) являются всегда строки, т.е. не просто примитив, а именно примитив-строка.
> А как? Чесслово, интересно
Например, в Spidermonkey до версии 1.7, eval-у можно передать вызывающий контекст, тем самым получая доступ к внутреннему объекту переменных.
function A() { var x = 10; // "private" this.getX = function () { return x; }; } var a = new A; a.getX(); // 10 eval('x = 20', a.getX); a.getX(); // 20
Благодарю за совет — я доработал библиотеку. Выигрыш в 60 раз без расходования памяти. :^)
> т.е. не просто примитив, а именно примитив-строка
Я знаю, но в данном случае проверяется всё равно на instanceof Number. :^)
> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)
Да, я здесь лишнего написал. Извините.
> можно передать вызывающий контекст
От таких вещей, к сожалению, защититься не получится. По крайней мере, сейчас я не знаю — как.
> т.е. не просто примитив, а именно примитив-строка
Я знаю, но в данном случае проверяется всё равно на instanceof Number. :^)
> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)
Да, я здесь лишнего написал. Извините.
> можно передать вызывающий контекст
От таких вещей, к сожалению, защититься не получится. По крайней мере, сейчас я не знаю — как.
Да, и спасибо за указание на опечатку — исправил.
Sign up to leave a comment.
Простой способ сделать «дешёвый» Private в JS