| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: Общие вопросы > Особенности Closure |
| Автор: Се ля ви 30.6.2008, 15:06 | ||||
| Не перестаю удивляться JavaScript`у. Вот, тут заметил, что, с одной стороны, аргументы конструкторов автоматически попадают в категорию private-полей:
С другой стороны, оно не просто является private-полем, но ещё и является неистребимым - попытка их удалить, что бы не таскать за собой, приводит к неудаче:
Так что на этот раз придётся Магомету идти к горе и обзывать входящие параметры конструктора так, как вы хотите назвать private-поля, ими инициализируемые. Это не есть интуитивно понятно, если не знать этой хитрости, но если её знать и грамотно использовать - это может заметно сэкономить объём вашего кода ;) |
| Автор: Се ля ви 30.6.2008, 15:36 |
| Насчёт delete x проверил - вообще-то ни одно private-поле так не удалишь, так что нужно об этом помнить, когда его создаёшь. (Для освобождения памяти, который занимает объект, доступный по ссылке, можно присвоить ссылке значение null, но на самом деле это не равнозначно отсутствию ссылки - ссылка будет всё равно). Но если вам на самом деле не нужен тот аргумент, который вы приняли в конструкторе, в последствии - то следует отказаться от именованных аргументов вообще и обращаться к ним по индексам "массива" arguments - это гарантирует удаление ссылок после выполнения конструктора. |
| Автор: Се ля ви 30.6.2008, 16:10 | ||||
В общем, резюме такое: за конструкцией
на самом деле стоит следующее:
|
| Автор: Се ля ви 1.7.2008, 11:07 | ||||
Мда... А ты уверен, что arguments дочерней функции именно перекрывает, а не выталкивает arguments родительской? Ведь поведение этого фрагмента кода можно объяснить и по-другому - что ты оставляешь дополнительную ссылку на arguments родителя и в следствии этого она не забирается сборщиком мусора, а не было бы ссылки - может, собралась бы или была бы замещена новым arguments?.. Но если правда то, что ты пишешь, тогда, блин, я не знаю, что себе думали создатели спецификации... Получается, что использовать аргументы в конструкторах и в функциях, которые генерят другие функции - это таскать за собой эти аргументы хвостом в течении всего жизненного цикла этих объектов и этих генерируемых функций... А если они нафиг не нужны - их даже прямо удалить нельзя... :((( Как-то это расточительно выглядит... :( Получается, что единственный выход - обnullять вручную формальные параметры в тех случаях, когда они могут попасть в closure - что бы хоть ненужные объекты память не захламляли. При чём обnullять как по именам, так и в "массиве" arguments, что бы ссылок на эти объекты не оставалось. Тогда мы будем таскать за собой пустые ссылки, но хотя бы не будем таскать объекты... Хотя выглядит это, конечно, не очч... :((( |
| Автор: dsCode 1.7.2008, 12:01 | ||||||
ага
именно так работают замыкания; на момент использования внутренней функции, внешней уже может не быть, поэтому весь (!) скоп (набор variable object'ов (VO)) приплюсовывается к скопу замыкания (это и есть scope-chain, который хранится во внутреннем свойстве [[scope]]) "именованные" и индексные взаимозаменяемы:
а вот, когда обnullять - до или после определения замыкания - не важно - переменная x (пример ниже) - "свободная" для VO функции b (т.е. ее нет в родном VO функции b), поэтому будет искаться по цепи скопов и найдется в VO функции a (которой уже может не быть); мы обnullяем свойство x VO функции a, поэтому alert выдает null, а не 5:
|
| Автор: Се ля ви 2.7.2008, 10:38 | ||||
Тогда для предотвращения утечек памяти можно просто в конце каждой функции, где может произойти "короткое замыкание" ;) вставлять примерно следующее:
P.S. Кстати, обнаружил, что var`ы - чрезвычайно живучи. До этого думал, что они по аналогии с Java - умирают когда выходишь за пределы любого блока, в котором они объявлены, но оказывается - нифига:
Так что это верно только для функции в целом, но не для её под-блоков. Поэтому я в качестве счётчика в предыдущем примере использовал "подручный материал", а не стал заводить новую переменную, как я это обычно делаю в той же Java. |
| Автор: dsCode 2.7.2008, 11:54 |
конечно, нифига =) но, в http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Block_scope_with_let алтернативой var'ам (чей локальный скоп - функция), появились let'ы, которые создают локальный скоп в нужном месте (их как раз можно использовать в циклах) |
| Автор: Се ля ви 2.7.2008, 12:55 | ||
Здорово! Жаль только, что, http://en.wikipedia.org/wiki/JavaScript#Versions, поддерживается всё, что дальше JS 1.5 - только в Gecko и Safari... :((( |
| Автор: Ghirik 5.7.2008, 06:15 | ||||
В JavaScript-е var для того и есть чтобы задать живучесть объявляемуму элементу. И видимо, по задумке сочинителей, он должен поддерживать контекст в котором задается, но соблюсти это правило удается не всем создателям интерпретаторов. Это в большей мере касается вложенных функций и головоломок, вроде наследования свойств, объявленных не понятно под каким соусом. Вообще, манера программирования в древовидном стиле, меня почему то бесит, что то есть в этом нездоровое. Зачем? Потом не можем разобраться кто и где родился, и сколько проживет. Не проще ли просто избегать таких ситуаций? Конечно здорово ощущать себя суперменом, когда написал функцию, которая имеет пять степеней вложенности и ни где не замыкает. Но это только для тренировки, или для нечитаемости. Последний момент конечно очень важен, если научишся так мыслить, вложенно, типа своей стилистики.... Но оно того не стоит.
Ну да, давайте ещё леты поддержим во всех браузерах! Для какой такой экстренной помощи потребовалось? Блочность данных и так можно спокойно обеспечивать и за ненадобностью удалять, всё вместе со всеми объявлениями. Если создавать все элементы навешивая их на любой действующий объект дерева, то при удалении самого объекта память высвобождается в любом браузере сразу. Там уже действуют обычные DOM-правила. Такой подход очень удобен при работе с html-элементами. Главное, ни var ни let вообще не нужны. Создавайте любой массив свойством к имеющемуся в дереве объекту. Тысячу массивов... Хакните элемент, - и массивы хакнутся, и память очистится. А передавать параметры обработчикам вообще не потребуется, вы их до того повесите на этот элемент свойствами. Мне нравится такой подход. |
| Автор: dsCode 8.7.2008, 21:17 | ||||
Хороший подход, только обращение к свойствам DOM-объектам - медленнее, чем к переменным JS. Простой пример: при очень больших циклах целесообразно (для оптимизации скорости) вынести свойство length в переменную (т.к. оно вычисляется на каждой итерации цикла):
А теперь, возвращаясь к теме "неистребимых" var'ов (чтобы более точно сказать о них) - в 10.2.2 Eval Code ничего не сказано про {DontDelete}, поэтому var'ы, полученные через eval, можно удалить.
|
| Автор: Се ля ви 22.7.2008, 16:27 | ||
А ещё можно let`ы эмулировать так:
|