Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Особенности Closure 
:(
    Опции темы
Се ля ви
Дата 30.6.2008, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Не перестаю удивляться JavaScript`у. smile
Вот, тут заметил, что, с одной стороны, аргументы конструкторов автоматически попадают в категорию private-полей:
Код
function c1 (x){
    
    this.getArg = function(){
        return x;
    }    
}

//Test:
alert((new c1(5)).getArg());//5


С другой стороны, оно не просто является private-полем, но ещё и является неистребимым - попытка их удалить, что бы не таскать за собой, приводит к неудаче:
Код
function c1 (x){
    
    alert(delete x);//false!
    
    this.getArg = function(){
        return x;
    }
    

}

//Test:
alert((new c1(5)).getArg());//5


Так что на этот раз придётся Магомету идти к горе и обзывать входящие параметры конструктора так, как вы хотите назвать private-поля, ими инициализируемые. Это не есть интуитивно понятно, если не знать этой хитрости, но если её знать и грамотно использовать - это может заметно сэкономить объём вашего кода ;)


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Се ля ви
Дата 30.6.2008, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Насчёт delete x проверил - вообще-то ни одно private-поле так не удалишь, так что нужно об этом помнить, когда его создаёшь. (Для освобождения памяти, который занимает объект, доступный по ссылке, можно присвоить ссылке значение null, но на самом деле это не равнозначно отсутствию ссылки - ссылка будет всё равно).

Но если вам на самом деле не нужен тот аргумент, который вы приняли в конструкторе, в последствии - то следует отказаться от именованных аргументов вообще и обращаться к ним по индексам "массива" arguments - это гарантирует удаление ссылок после выполнения конструктора.


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Се ля ви
Дата 30.6.2008, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



В общем, резюме такое: за конструкцией

Код
function f1(x){
    //...
}


на самом деле стоит следующее:
Код
function f2(){
    var x = arguments[0];

    //...
}



--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
dsCode
Дата 30.6.2008, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  30.6.2008,  15:36 Найти цитируемый пост)
то следует отказаться от именованных аргументов вообще и обращаться к ним по индексам "массива" arguments - это гарантирует удаление ссылок после выполнения конструктора. 

неа, скоп внешней функции "оседает" в замыкании при создании замыкания (единственная разница (проблема), что вы не сможете различить arguments внешней функции по этому имени ("arguments"), т.к. объект с таким именем "не свободный" (т.е. будет найден сразу в скопе замыкания)):

Код

function a() {
  var args = arguments; // имя args только для того, чтобы различить arguments внутри b
  return function b() {
    alert([args[0], arguments[0]]);
  }
}

a(5)(6);


Цитата(Се ля ви @  30.6.2008,  15:06 Найти цитируемый пост)
С другой стороны, оно не просто является private-полем, но ещё и является неистребимым


любым var'ам ставится {DontDelete} (и нет никаких различий между "просто private-полями" и "неистребимыми" =)) объявите глобальную переменную var a = 10; - alert(window['a']); - она никакая не приватная, delete window['a'] - ничего не получится.

Цитата(Се ля ви @  30.6.2008,  16:10 Найти цитируемый пост)
В общем, резюме такое:


в общем, резюме опять лежит в 10.1.3 Variable Instantiation и то, что вы написали var x = arguments[0]; от первого случая ничем не отличается, кроме дополнительной работы - и там, и там x станет свойством Variable Object'a (правда, объявление undefined'ых var'ов внутри функции никак не "перезатрет" формальный параметр):

Код

function a(x) {
  var x; // казалось бы, - должны перезаписать
  alert(x); // но нет, x - 5, а не undefined
}

a(5);


Но с другой стороны, объявление функции (которая тоже будет свойством Variable Object'a) имеет больший приоритет и перезаписывает var'ы:

Код

function a(x) {
  x(); // x - функция (хоть и объявлена ниже), а не 5
  function x() {
    alert('x');
  }
}
a(5);



Это сообщение отредактировал(а) dsCode - 30.6.2008, 19:38


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 1.7.2008, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(dsCode @  30.6.2008,  19:17 Найти цитируемый пост)
скоп внешней функции "оседает" в замыкании при создании замыкания (единственная разница (проблема), что вы не сможете различить arguments внешней функции по этому имени ("arguments"), т.к. объект с таким именем "не свободный" (т.е. будет найден сразу в скопе замыкания)):
    
Код
function a() {
  var args = arguments; // имя args только для того, чтобы различить arguments внутри b
  return function b() {
    alert([args[0], arguments[0]]);
  }
}
a(5)(6);

Мда... А ты уверен, что arguments дочерней функции именно перекрывает, а не выталкивает arguments родительской? Ведь поведение этого фрагмента кода можно объяснить и по-другому - что ты оставляешь дополнительную ссылку на arguments родителя и в следствии этого она не забирается сборщиком мусора, а не было бы ссылки - может, собралась бы или была бы замещена новым arguments?..

Но если правда то, что ты пишешь, тогда, блин, я не знаю, что себе думали создатели спецификации... Получается, что использовать аргументы в конструкторах и в функциях, которые генерят другие функции - это таскать за собой эти аргументы хвостом в течении всего жизненного цикла этих объектов и этих генерируемых функций... А если они нафиг не нужны - их даже прямо удалить нельзя... :(((

Как-то это расточительно выглядит... :(

Получается, что единственный выход - обnullять вручную формальные параметры в тех случаях, когда они могут попасть в closure - что бы хоть ненужные объекты память не захламляли. При чём обnullять как по именам, так и в "массиве" arguments, что бы ссылок на эти объекты не оставалось. Тогда мы будем таскать за собой пустые ссылки, но хотя бы не будем таскать объекты...

Хотя выглядит это, конечно, не очч... :(((


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
dsCode
Дата 1.7.2008, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  1.7.2008,  11:07 Найти цитируемый пост)
А ты уверен

ага

Цитата(Се ля ви @  1.7.2008,  11:07 Найти цитируемый пост)
таскать за собой эти аргументы хвостом в течении всего жизненного цикла этих объектов и этих генерируемых функций

именно так работают замыкания; на момент использования внутренней функции, внешней уже может не быть, поэтому весь (!) скоп (набор variable object'ов (VO)) приплюсовывается к скопу замыкания (это и есть scope-chain, который хранится во внутреннем свойстве [[scope]])

Цитата(Се ля ви @  1.7.2008,  11:07 Найти цитируемый пост)
При чём обnullять как по именам, так и в "массиве" arguments

"именованные" и индексные взаимозаменяемы:

Код

(function a(x) {
  alert(x === arguments[0]); // true
  var x = 10;
  arguments[0] = 5;
  alert(x); // 5
})(5);


а вот, когда обnullять - до или после определения замыкания - не важно - переменная x (пример ниже) - "свободная" для VO функции b (т.е. ее нет в родном VO функции b), поэтому будет искаться по цепи скопов и найдется в VO функции a (которой уже может не быть); мы обnullяем свойство x VO функции a, поэтому alert выдает null, а не 5:

Код

(function a(x) {
  function b() {
    alert(x);
  }
  x = null;
  return b;
})(5)();


Это сообщение отредактировал(а) dsCode - 1.7.2008, 12:08


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 2.7.2008, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(dsCode @  1.7.2008,  12:01 Найти цитируемый пост)
"именованные" и индексные взаимозаменяемы

Тогда для предотвращения утечек памяти можно просто в конце каждой функции, где может произойти "короткое замыкание" ;) вставлять примерно следующее:

Код
if (arguments.length)
    for (arguments[0] = arguments.length; arguments[0];)
        arguments[--arguments[0]] = null;


P.S. Кстати, обнаружил, что var`ы - чрезвычайно живучи. До этого думал, что они по аналогии с Java - умирают когда выходишь за пределы любого блока, в котором они объявлены, но оказывается - нифига:
Код
if (true) {
        var y = 5;
    }
    
    alert(y);//5

Так что это верно только для функции в целом, но не для её под-блоков. Поэтому я в качестве счётчика в предыдущем примере использовал "подручный материал", а не стал заводить новую переменную, как я это обычно делаю в той же Java.


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
dsCode
Дата 2.7.2008, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  2.7.2008,  10:38 Найти цитируемый пост)
но оказывается - нифига:

конечно, нифига =) но, в версии 1.7 алтернативой var'ам (чей локальный скоп - функция), появились let'ы, которые создают локальный скоп в нужном месте (их как раз  можно использовать в циклах)


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 2.7.2008, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(dsCode @  2.7.2008,  11:54 Найти цитируемый пост)
в версии 1.7 алтернативой var'ам (чей локальный скоп - функция), появились let'ы, которые создают локальный скоп в нужном месте (их как раз  можно использовать в циклах)

Здорово! Жаль только, что, согласно WikiPedia`и, поддерживается всё, что дальше JS 1.5 - только в Gecko и Safari... :(((


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Ghirik
Дата 5.7.2008, 06:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 919
Регистрация: 26.3.2007

Репутация: 13
Всего: 20



Цитата

но оказывается - нифига


В JavaScript-е var для того и есть чтобы задать живучесть объявляемуму элементу. И видимо, по задумке сочинителей, он должен поддерживать контекст в котором задается, но соблюсти это правило удается не всем создателям интерпретаторов. Это в большей мере касается вложенных функций и головоломок, вроде наследования свойств, объявленных не понятно под каким соусом. Вообще, манера программирования в древовидном стиле, меня почему то бесит, что то есть в этом нездоровое. Зачем? Потом не можем разобраться кто и где родился, и сколько проживет. Не проще ли просто избегать таких ситуаций?

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

Цитата

Жаль только, что, согласно WikiPedia`и, поддерживается всё, что дальше JS 1.5 - только в Gecko и Safari... 


Ну да, давайте ещё леты поддержим во всех браузерах!
Для какой такой экстренной помощи потребовалось?

Блочность данных и так можно спокойно обеспечивать и за ненадобностью удалять, всё вместе со всеми объявлениями. Если создавать все элементы навешивая их на любой действующий объект дерева, то при удалении самого объекта память высвобождается в любом браузере сразу. Там уже действуют обычные DOM-правила. Такой подход очень удобен при работе с html-элементами. Главное, ни var ни let вообще не нужны. Создавайте любой массив свойством к имеющемуся в дереве объекту. Тысячу массивов... Хакните элемент, - и массивы хакнутся, и память очистится. А передавать параметры обработчикам вообще не потребуется, вы их до того повесите на этот элемент свойствами. Мне нравится такой подход.





--------------------
Отдадим всё клиенту, пускай его машина мучается...

PM MAIL   Вверх
dsCode
Дата 8.7.2008, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Ghirik @  5.7.2008,  06:15 Найти цитируемый пост)
Мне нравится такой подход.

Хороший подход, только обращение к свойствам DOM-объектам - медленнее, чем к переменным JS. Простой пример: при очень больших циклах целесообразно (для оптимизации скорости) вынести свойство length в переменную (т.к. оно вычисляется на каждой итерации цикла):

Код

for (var k = 0, length = объектDOM.length; k < length; k++) {
 ...
}


А теперь, возвращаясь к теме "неистребимых" var'ов (чтобы более точно сказать о них) - в 10.2.2 Eval Code ничего не сказано про {DontDelete}, поэтому var'ы, полученные через eval, можно удалить.

Код

(function () {
  eval('var a = 10;');
  alert(a);
  delete a;
  alert(a);
})();



Это сообщение отредактировал(а) dsCode - 8.7.2008, 22:53


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 22.7.2008, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



А ещё можно let`ы эмулировать так:
Код

...
(function(){
    var x;
    x = 5;
...
})();
...

smile


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0657 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.