Цитата:
Цитата:
Цитата:
из того же контекста где эти переменные известны мы же однозначно их определяем ?.. Впрочем, вот сам опровергну свои слова, хотя не понимаю, зачем так сделано : var a = 10; function b(x) { var c = 20; // Здесь пытаемся вызвать из контекста b, в котором однозначно какзалось бы определяются все значения VO(b) if (x) { a=5; c=7; x(); return } ; // 30,0,5 <- НИКАКОГО влияния нового c==7 ! осталось старое законсервированное c==0 function d() { var e = 30; al( [e ,c , a ]); }; // Замыкаем на savB var savB=d; // Scope Chain (b) === [[Scope]](d) Зачем Здесь хранить Scope Chain (b) ? savB(); // 30,20,10 c=0; // Если бы VO(b) законсервировался при замыкании, то это изменение // НЕ оказало бы воздействия на последующий вызов через Замыкание: savB(); // 30,0,10 <- Scope Chain (b), т.е. VO(b) - не законсервировался, т.к. // здесь вызов почувствовал (?) изменение с с=20 на --> c=0 // НО ПОЧЕМУ ????????????????? ЗДЕСЬ [[Scope]](d) НЕ СОХРАНИЛСЯ b(savB); // 30,0,5 <- А вот так НЕ почувствовал с=7 , хотя контекст b, казалось бы мог сам определить свои значения, Караул !!! return savB; }; var s=b(); //s(); // 30,0,10 <- Scope Chain (b), т.е. VO(b) - Законсервировался, но Global - нет. // b(s); // 30,0,5 s(); // 30,0,5 Но уж Global'то VO - никогда не консервируется при замыканиях ?! PS. Можно еще пояснить вопрос НО ПОЧЕМУ?????????? в примере ? Просто я считал, что Замыкание необходимо для разрешения неоднозначности значений локальных переменных из [[Scope]] замыкаемой функции, которая возникает , если ссылка на функцию сохраняется вне Контекста охватывающей функции и мы захотим вызвать функцию Извне ее Охватывающего Контекста по этой ссылке. |
Цитата:
Когда вы отправляете функцию 'd' в качестве аргумента, то у функции 'b' создаётся собственный новый VO(b), но 'd' это не волнует, т.к. неё другой VO(b), созданный ранее при первом вызове. Соответственно, свойство 'c' одного объекта не имеет никакого отношения к свойству 'c' другого объекта... |
Цитата:
|
Все правильно сказано, но вот что-то не достает для практического руководства, т.е. нужны какие-то
краткие , чтобы легко запомнить и одновременно предельно ясные, чтобы не ошибиться слова , поясняющие явление Замыкания. У меня вот тоже не очень получается сложить такие слова. попытался вот так, исправьте,плз, что не так : /* Когда Программа может менять слоты [[Scope]]'a' Замыкания : [[Scope]] Замыкания - [[Scope]] замыкаемой функции. Он Живой пока есть ссылка на Замыкаемую функцию (т.е. Замыкание). Контекст Замыкания - Весь Внешний контекст Замыкаемой функции, т.е. Весь Контекст в который она вложена. Все вызовы через Замыкание происходят с использованием [[Scope]]-а Замыкания для определения в вызываемой функции значений свободных переменных, точнее слотов [[Scope]]'а Замыкания . В случае выхода управления на Верхний уровень Программе оказываются доступными только слоты [[Scope]]'а' Замыкания для [[Scope Chain]]'а' этого уровня, т.е. только [[VO]]Global. Если управление выходит из Контекста Замыкания не полностью, а на какой-то его Уровень, то Программе на этом Уровне становятся доступными ТОЛЬКО слоты [[Scope]]'а' Замыкания для [[Scope Chain]]'а' этого уровня , При дальнейшем входе с этого Уровня на Вложенные уровни, вновь создаваемые [[VO]] вложенных уровней ЗАКРЫВАЮТ(консервирует) сответствующие [[VO]] для этих уровней из [[Scope]]'а' Замыкания. Программма всегда может получить доступ ко всему [[Scope]]'у' Замыкания передав управление в Замкнутую функцию ЧЕРЕЗ Замыкание. */ function al(o){document.write(o,'<br>')} ; al('g,a,b,c ---------------'); var myScope , g = 0 ; A(); function A(x) { // Вход сюда создает новый [[VO]]A ,но не затрагивает [[VO]]Global === ( [[Scope]]A == [ myScope, g==0 ] ) var a = 1; if (x==1) { a=2; b=2; c=2; al( [g, a, b, c, '<---A( )'] ); myScope(2) ; return } ; if (x==2) { al( [g, a, b, c, '-- имеем в A( )']); return } ; B(); function B(y) { // Вход сюда создает новый [[VO]]B ,но не затрагивает [[VO]]А,[[VO]]Global var b = 1; if (y==1) { a=3; b=3; c=3; al( [g, a, b, c, '<---B( )']); myScope(2); return } ; if (y==2) { al( [g, a, b, c, '-- имеем в B( )']); return } ; C(); function C(z) { // Вход сюда создает новый [[VO]]С ,но не затрагивает [[VO]]B, [[VO]]А ,[[VO]]Global var c=1; if (z==1) { a=4; b=4; c=4; al( [g, a, b, c, '<---C( )']); myScope(2); return } ; if (z==2) { al( [g, a, b, c, '-- имеем в C( )']); return } ; // myScope = B ; // [[Scope]]B == [ myScope, g==0,a==1,x, B ] // Замкнуть, Контекстом Замыкания будет весь Внешний Контекст функции C : myScope = C ; // [[Scope]] Замыкания [[Scope]]C == [ myScope, g==0,a==1,b==1, x, y, B, C ] // g,a,b,c --------------- // 0,1,1,1,-- имеем в C( ) // <-исходное состояние [[Scope]]'а' Замыкания myScope(2); // Выход на уровень Контекста Global - Полный выход из Контекста Замыкания, В вызываемой функции A // никакие слоты [[Scope]]'a' Замыкания не доступны, кроме [[Scope]]A === [[VO]]Global слотов (ни а ни b не изменить) // 0,2,2,2,<---A( ) // 0,1,1,1,-- имеем в C( ) A(1); // Выход на Уровень Контекста А - Частичный выход из Контекста Замыкания, // в вызываемой B() будут доступны только слоты [[Scope]]'a' Замыкания для [[Scope]]B ( a можем изменить, b -нет ) // 0,3,3,3,<---B( ) // 0,3,1,1,-- имеем в C( ) // 0,3,3,1,-- имеем в C( ) для вызова C(2) вместо myScope(2),т.е. b меняем ! B(1); // Выход на уровень Контекста B, Нет выхода из Конекста Замыкания, // в вызываемой С() будут доступны все слоты [[Scope]]'a' Замыкания для [[Scope]]C (a и b можно изменить) C(1); return; // Выход на уровень Контекста B // 0,4,4,4,<---C( ) // 0,4,4,1,-- имеем в C( ) }; return ; // Выход на уровень Контекста A }; return ; // Выход на уровень Контекста Global - Полный выход из Контекста Замыкания }; |
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
краткие , чтобы легко запомнить и одновременно предельно ясные, чтобы не ошибиться слова, и потом, не совсем про то, что такое Замыкание, а про ... см ниже Цитата:
Мне кажется Дело бы при Замыканиях было бы довольно просто , если бы [[Scope]]Замыкания не менялся. Тогда бы - как только замкнули (myScope = C), - проанализировали кусок кода, где замкнули, поняли для себя , какие там должны быть значения слотов [[Scope]]Замыкания и вуа-ля - спокойно используем, надежно зная и понимая , какие значения будут у переменных [[Scope]]Замыкания при вызове замкнутой функции через Замыкание ( myScope(2) ) - НЕТ никаких проблем ! НО ! Вот после того, как замкнули, этот пресловутый [[Scope]] Замыкания может еще меняться программой ДО того, как стали вызывать Замкнутую функцию через Замыкание и проанализировать это довольно не просто. И поэтому я и привел пример (причем ,довольно интересный, с частичным выходом из Контекста Замыкания), иллюстрирующий наиболее ясно эту проблему и попытался максималоьно кратко дать объяснение - Когда Программа может менять слоты [[Scope]]'a' Замыкания . Поэтому непонятно ТОЛЬКО одно (нет , ну, конечно, непонятным при обнаружении новых фактов может стать все , что угодно ), но пока это : - КАК максимально кратко и ясно описать основную проблему при работе с Замыканиями - Когда Программа может менять слоты [[Scope]]'a' Замыкания ? Я попытался так , как попытался, Вы считаете, что плохо, или не хотите "расшифровывать примеры", не знаю ... |
Цитата:
function A() { // в момент создания [[Scope]] функции 'В' // переменной 'x' вообще не существует function B() { alert(typeof x); } // в момент вызова тоже B(); eval('var x = 1'); // теперь есть B(); } A(); |
Часовой пояс GMT +3, время: 06:33. |