Search
Write a publication
Pull to refresh

Comments 9

Здесь мы экономим ресурсы за счёт того, что создаваемая каждый раз в конструкторе функция состоит всего из одной строки — вызова настоящего тела метода.

Весьма странное понимание проблемы. Код функций никогда не копируется, поэтому от их размера ничего не зависит. Повышенное потребление памяти связано с тем, что каждый экземпляр функции хранит свое окружение (closure), т.е. ссылки на переменные из внешних областей видимости.

В данном же случае хранение ссылок на переменные заменяется копированием методов приватного объекта в публичный, что сравнимо по объему. Так что весьма сомнительно, что это даст какой-нибудь выигрыш. Тесты прогоняли?

> Код функций никогда не копируется, поэтому от их размера ничего не зависит.

Зависит от типа функции. Стандарт предусматривает оптимизацию в виде объединённых объектов, но там должны соблюдаться определённые условия. Новая версия стандарта (ECMA-262-5, текущий драфт) определяет внутреннее свойство [[Code]], которое может реюзаться между (объединёнными) функциями, но в текущей версии стандарта об этом ничего не сказано (хотя, на практике, я думаю, реализации делают оптимизацию, включая предложенную с объединёнными объектами). Но, повторю, зависит это от типа функций. Разбирал это в пятой части статей об ECMAscript.
kriomant, в принципе вы правы, создаётся новое замыкание (а дублирование кода действительно зависит от браузера). Но я, очевидно, немного неверно сформулировал мысль: обратите внимание, что все private-методы выносятся за пределы определения класса, и, следовательно, сам класс о них ничего не знает и никак их не дублирует — а как правило таких методов больше, чем публичных, работающих с ними (это уже просто практика), которые и создаются в конструкторе. Тесты показывают, что выигрыш действительно есть — где-то в 1,8 раза (например, 0,768 против 0,454 для создания 1000 объектов с 1000-ей закрытых и 1000-й открытых методов).

А вот с приведённым решением с сервером объектов, ради которого статья и затевалась, получается интереснее — это решение работает приблизительно в 7 раз быстрее во всех браузерах, кроме Firefox (там медленнее)… но только при первом прогоне — потом (при обновлении страницы) и лис прекрасно обрабатывает его.

Такая вот получается картина.
Простите, забыл упомянуть: ну а по памяти, я думаю, выигрыш очевиден.
Интересное решение, своеобразное ;). А какова основная цель? Публичные (external) свойства копируются, что увеличивает расход ресурсов.

> if(objects[_id].Eexternal

Опечатка.

> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)

Ну блин, ещё бы, совершенно новый независимый объект Number создаётся, никак не связанный с данной обёрткой (не имеющий расширенных, скопированных свойств) ;)

В целом, не считая недочётов, что extenral stuff копируется в каждый новый объект, а не наследуется, а также, не считая того, что в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs» и обратиться к нужному «скрытому» объекту, — идея своеобразно-интересная ;)

P.S.: немного затрагивал тему инкапсуляции (с позиции восприятия) в седьмой части статей об ECMAscript.
> Ну блин, ещё бы, совершенно новый независимый объект Number

На самом деле индексом в массиве объектов является примитив, так что проверка нужна.

> extenral stuff копируется в каждый новый объект, а не наследуется

Я сейчас как раз ищу решение, как его унаследовать. :^) Это, я надеюсь, позволит избавиться от перерасхода ресурсов и от тормозов в лисе при первом прогоне. Спасибо за совет.

> в некоторых реализациях, всё-таки, можно получить доступ к инкапсулированному var-у «objs»

А как? Чесслово, интересно. Может, это позволит сделать что-нибудь интересное. :^)
> На самом деле индексом в массиве объектов является примитив, так что проверка нужна.

Да нет, я имею в виду, Вы пишите:

# 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. :^)

> И можно не опасаться, что кто-то переопределит номер объекта — сервер откажет такому запросу (см. две последние стоки)

Да, я здесь лишнего написал. Извините.

> можно передать вызывающий контекст

От таких вещей, к сожалению, защититься не получится. По крайней мере, сейчас я не знаю — как.
Да, и спасибо за указание на опечатку — исправил.
Sign up to leave a comment.

Articles