Цитата:
Цитата:
Цитата:
из того же контекста где эти переменные известны мы же однозначно их определяем ?.. Впрочем, вот сам опровергну свои слова, хотя не понимаю, зачем так сделано :
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:26. |