Цитата:
Цитата:
Цитата:
|
2 Zeroglif >
мда, что-то мутно там. Мог бы кто понятно объяснить эти [[scope]], VO, контекст и иже с ними (какие-то, оказывается, еще спец объекты бывают ... ) , какие из этих объектов когда создаются, что они содержат и какие из них свойствами каких являются : - при доRUN-time'оых FD определениях функций , - при FE определениях функций , - при вызове функций ? |
Вообще, там достаточно информации было, но попробую ещё проще; по частям, чтобы "уварилось". Начнём с VO.
Variable object (Объект переменных, сокращённо VO) - это объект, служащий хранилищем для: 1. переменных (var); 2. деклараций функций (function declaration, FD); 3. формальных параметров функции; Главной особенностью здесь является то, что VO наполняется при входе в контекст, т.е. до выполнения кода контекста. Причём, в случае var'ов и недостающих формальных параметров под "наполнением" подразумевается резервирование слотов в VO со значением undefined. Пример: function test(a, b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } test(10); // вызов Этапы вызова: 1. Вход в контекст: VO = { // упрощённо; в реале он "наследуется" от Объекта активации a: 10, b: undefined, c: undefined, d: <reference to functionBody> e: undefined }; 2. Исполнение контекста: VO['c'] = 10; VO['e'] = <reference to "_e" functionBody>; Всё. Как видим, функция "x", являясь FE (function expression), а не FD, не попала в VO (поскольку, ничего не было сказано про воздействие FE на VO в пунктах выше). Если попробовать вызвать функцию "x" за пределами объявления - будет ReferenceError. С другой стороны, "_e" также является FE, но последующее присвоение её переменной "e" оставляет на неё ссылку через VO["e"]. Если здесь всё понятно, и есть желание дальше изучать, можно будет продолжить. update: Эм.. Оказывается, я уже в этой теме писал почти тоже самое. |
Цитата:
а еще есть arguments, [[scope]] , etc ... Да, и еще бы понять, чьи они свойства - если функции , то в глобальном контексте если находимся - тогда чьи ? |
Цитата:
Кстати, в предыдущем посте, говоря о VO, в большей мере имелся в виду VO функции. AO создаётся при входе в контекст функции и инициализируется свойством arguments, значением которого является Arguments object (Объект аргументов, обозначим ArgO, чтобы не путать с AO): AO = { arguments: <ArgO> }; Далее, этот AO становится ничем иным как VO. Поэтому, говоря о VO в контексте типа "функция", можно использовать и терминологию AO, т.к. здесь VO === AO. Образно в предыдущем посте (чтобы не перегужать и не приплетать arguments) я назвал это "наследуется", физически же, это тот же самый объект. Говоря о VO в глобальном контексте, - сам глобальный объект является VO (в браузере - window). Цитата:
- callee - ссылка на выполняемую функцию; - length - количество реально переданных параметров; - свойства-индексы (числовые, приведённые к строке), значения которых есть формальные параметры функции (слева направо в списке параметров). Количество этих свойств-индексов == arguments.length. Значения свойств-индексов объекта arguments и присутствующие формальные параметры - взаимозаменяемы: function a(x, y, z) { alert(arguments.length); // 2 alert(arguments.callee === a); // true alert(x === arguments[0]); // true alert(x); // 10 arguments[0] = 20; alert(x); // 20 x = 30; alert(arguments[0]); // 30 } a(10, 20); Цитата:
Если всё понятно, можно будет продолжить про [[Scope]]. |
Я понял так , еще немного допридумал, чтобы было логичнее, проверьте что не так :
Variable object (Объект переменных, сокращённо VO) - это объект, служащий хранилищем для: 1. переменных (var); 2. деклараций функций (function declaration, FD); 3. формальных параметров функции; Главной особенностью здесь является то, что VO наполняется при входе в контекст, т.е. до выполнения кода контекста. Причём, в случае var'ов и недостающих формальных параметров под "наполнением" подразумевается резервирование слотов в VO со значением undefined. Для глобального контекста : VO===Global (где Global - встроенный глобальный объект) нашпиговывается ДО run-time слотами, которые по мере работы программы могут менять свои значения, но не свое количество или имена ! Для функции : Если не было входа управления в контекст функции, то не существует для нее никакого ни VO, ни AO. Если управление вошло во внутренний контекст функции F , то ДО ее выполнения для этой функции создается свой VO', при этом выполняются след шаги : arguments = [<0аргумент>,<1аргумент,...]; arguments.callee=F; arguments.length=<КолвоАргументовФункции_F>; AO = { arguments: arguments }; F.VO=AO; При выходе из контекста функции выполняется : delete F.VO Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Scope (Scope chain, Иерархия областей видимости (в данном переводе)) - это цепь Объектов переменных, в которой происходит поиск значений при разрешении имен идентификаторов. Данная цепь создаётся при выполнении функии, и состоит из VO(текущей функции) и [[Scope]] функции: Scope = VO + [[Scope]]. Можно ещё раз здесь почитать. Пример: var a = 10; function b() { var c = 20; function d() { var e = 30; alert(a + c + e); } d(); return d; } b(); Имеем: VO(Global): VO(Global) === Global = { a: 10 b: <reference to functionBody> }; При создании "b", [[Scope]] "b": [[Scope]](b) = [ VO(Global) ]; VO(b): VO(b) = { c: 20, d: <reference to functionBody> }; При запуске "b", Scope(b) = VO(b) + [[Scope]](b): Scope(b) = [ VO(b), VO(Global) ]; При создании внутрененней функции "d", [[Scope]] "d": [[Scope]](d) = [ VO(b), VO(Global) ]; VO(d): VO(d) = { e: 30 }; При запуске "d", Scope(d) = VO(d) + [[Scope]](d): Scope(b) = [ VO(d), VO(b), VO(Global) ]; Разрешение имён идентификаторов "a", "c" и "e" при alert'e: - "a" -- VO(d) - не найдено; -- VO(b) - не найдено; -- VO(Global) - найдено - 10. - "с" -- VO(d) - не найдено; -- VO(b) - найдено - 20. - "е" -- VO(d) - найдено - 30; Т.е. Scope опрашивается по цепи вверх, если идентификатор не найден в родном VO. При return d; остаётся ссылка на [[Scope]](d), поэтому все VO в цепи, стоящие иерархически выше - остаются в памяти. |
2 Dmitry A. Soshnikov >
Все яснее и яснее, Я сам-то мучился с этими терминами, понимал для себя только , что есть внешний контекст для каждой функции и внутренний. И как это все Вы поняли из ECMA спецификации , ума не приложу ... Кстати контекст, как я сейчас понимаю, не является термином обозначающим некий объект, это чисто лексический контекст для текста функции или какого-ни слова из кода программы ? Вот правда, еще остается непонятной роль AO - вроде как и нни к чему он , да еще какой-то непонятныйц остается спец объект из Вашей ссылки выше. Цитата:
- именно на [[Scope]] , т.е. БЕЗ VO функции d ? - и сохраняются не просто , если возвращается return, как в Вашем примере b() , а если возвращаемое где-то сохранено var q=b() ? |
Цитата:
Цитата:
Цитата:
Цитата:
(function fn() {alert(fn);})(); Откуда alert(fn) выдаёт правильное значение, если FE не воздействуют на VO? Идентификатор fn не должен был попасть в VO(Global). Где же FE его находит? Специально для этого перед созданием FE создаётся этот спец. объект и кладётся в scope chain (в данном случае Global): Scope(Global).{}.fn = <reference to FE "fn"> Дальше, когда создалась FE "fn", этот спец. объект удаляется из Scope(Global) - теперь он есть в [[Scope]](fn) и, соотвественно, может быть найден. Здесь ещё можно почитать. Цитата:
Цитата:
|
Цитата:
|
Цитата:
P.S.: надо бы сделать тег зачёркивания. |
Тут еще интересно c чисто хозяйственной точки зрения :
а сохраняется ли [[Scope]] (d), если функция d не содержит переменных из своего [[Scope]], в этом случае вроде как бы оно и не нужно тратить память ? Правда практически на тестах это не проверить никак . var a = 10; function b() { var c = 20; function d() { var e = 30; alert( e); } d(); return d; } var sav=b(); |
Цитата:
Цитата:
function a() { var b = 10; function c() { function d() { alert(b); } } } Функция "с" не использует переменные из внешнего VO (ещё говорят: не имеет свободных переменных). Однако, функция "d" - использует. И черпает из Scope, частью которого является [[Scope]] (т.е. Scope вышестоящего контекста). Для "d", [[Scope]] - это Scope(c), и если в "c" не будет ссылки на вышестоящий контекст (где находится "b"), "d" не увидит "b". |
Цитата:
И еще аналогичный вопрос : А сохраняется ли Scope Chain контекста в котором мы сделали замыкание? Тоже, вроде как, ни к чему . Т.е. var a = 10; function b() { var c = 20; function d() { var e = 30; alert( e); } d(); var savB=d; // Scope Chain (b) === [[Scope]](d) Здесь сохранится ? return d; } var sav=b(); |
Да, сохраняется. В спецификации ничего по этому поводу не сказано, сказано лишь, что [[Scope]] однозначно записывается в функцию при её создании. Однако, может, какие-то реализации могут делать оптимизацию (только в однозначно определённых случаях, когда точно известно, что функция не использует ничего извне), но это лишь предположение. С другой стороны, в функции может стоять if, внутри которого будет eval(...), использующий свойства из [[Scope]]. Или же функция может вызывать себя рекурсивно по имени (имя также находится в [[Scope]]).
|
2 Dmitry A. Soshnikov> Это ответ на первый или второй вопрос, во втором случае вроде как незачем сохранять Scope Chain ?
var a = 10; ( function b() { var c = 20; function d() { var e = 30; alert( e+c+a); } d(); var savB=d; // Scope Chain (b) === [[Scope]](d) Зачем Здесь хранить Scope Chain (b) ? return d; } ) () |
Цитата:
Возможно, какая-нибудь из реализаций не сохраняет [[Scope]] для оптимизации в функции вида function a() {}. Но, ещё раз, в спецификации ничего не сказано об этом. |
Цитата:
Может он-то и записывается , но записывается ссылка на него, но его содержимое ... , короче, вот : var a = 10; function b() { var c = 20; function d() { var e = 30; al( e+c+a); }; // Замыкаем на savB var savB=d; // Scope Chain (b) === [[Scope]](d) Зачем Здесь хранить Scope Chain (b) ? savB(); // 60 c=0; // Если бы VO(b) законсервировался при замыкании, то это изменение // не оказало бы воздействия на последующий вызов через Замыкание: savB(); // 40 <- Scope Chain (b), т.е. VO(b) - не законсервировался return savB; }; var s=b(); s(); //40 <- Scope Chain (b), т.е. VO(b) - Законсервировался, но Global - нет. |
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
из того же контекста где эти переменные известны мы же однозначно их определяем ?.. Впрочем, вот сам опровергну свои слова, хотя не понимаю, зачем так сделано : 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(); |
Цитата:
|
Цитата:
Т.е. для b - это не так , не из любого места ( см пример для B(1); ) и выхожу я в примере ( частично ) из контекста Замыкания. |
kefi, Вы что-то больше себя путаете, толком сами не определились, что хотите спросить (и что конкретно не понятно). Не надо подобных примеров с тучей комментарием, тучей переменных и т.д. Если хотите что-то понять, и осознать (и чтобы легко запоминалось) - надо делать это на примерах с "a" и "b" - не более.
Цитата:
Цитата:
Цитата:
Цитата:
P.S.: Цитата:
|
Цитата:
|
Все-таки жесть этот JavaScript.
Нужна лексическая область видимости -- юзайте лексическую, нужна динамическая -- используйте ее, опять же. А тут смешали бензин с кошачьим дерьмом, надеясь получить взрывную смесь, а получили... бензин с кошачьим дерьмом вперемешку. Пусть дан такой кодец: var x = 0; var f = function() { return x; } var g = function() { var x = 1; return f(); } Если область видимости динамическая, то g вернет 1, а если лексическая -- то 0. И не нужные никакие activation objects, [[SCOPE]] и прочая муть. :) Читать: http://en.wikipedia.org/wiki/Scope_(programming) или SICP, там отличные примеры. Ну и конкретно по JS: http://www.digital-web.com/articles/...in_javascript/ |
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
И , Кстати, причем здесь взрывная смесь? Без Замыканий при использовании функций в качестве переменных логически невозможно обойтись , даже если Вы не нуждаетесь ни в какой взрывной смеси. |
Цитата:
"Замыкания могут общаться через свои Скопы Замыкания" и это: "...с частичным выходом из Контекста Замыкания" и уж тем более: "Программма всегда может получить доступ ко всему [[Scope]]'у' Замыкания передав управление в Замкнутую функцию ЧЕРЕЗ Замыкание." p.s. и первый, и второй пример - совершенно обычные по своему поведению, всё абсолютно в рамках логики языка, немного усложнено рекурсией, но это ничего не меняет в схеме создания scope chain и в схеме разрешения идентификаторов. |
Цитата:
1) Цитата:
т.е. myScope(), а не через C(). Цитата:
Цитата:
Повторю их немного яснее. /* Более корректное Уточнение Замыкания . Замыкание - установка Защитника(Телохранителя) для Скопа Замыкания(см ниже). Пока он живой или пока живы те, кому его скопировали, СкопЗамыкания не убить. Защитником является переменная Замыкания (или просто 'Замыкание'), т.е. ссылка на замыкаемую функцию (переменная или фактический параметр). Установить Замыкание (Замкнуть) - можно ТОЛЬКО на Уровне(см ниже Уровни) Контекста Замыкания и вложенных. Установить - значит присвоить с помощью FE ссылку на функцию переменной или, точнее, просто использовать Имя Замыкаемой функции в выражении . Когда Программа может менять слоты [[Scope]]'a' Замыкания (основная проблема анализа Замыканий): [[Scope]] Замыкания - [[Scope]] замыкаемой функции. Он Живой пока живой его Защитник ссылка на Замыкаемую функцию. Контекст Замыкания - Весь Внешний контекст Замыкаемой функции, т.е. Весь Контекст в который она вложена. Все вызовы через Замыкание происходят с использованием [[Scope]]-а Замыкания для определения в вызываемой функции значений свободных переменных, точнее слотов [[Scope]]'а Замыкания . Уровни Контекста - Верхний(0 или Global),Первый(1 или функций Верхнего уровня(А функций)), Второй(2 или B) , etc ... ( Уровнем Контекста Замыкания считается не Global,а Уровень контекста Замыкаемой функции. ) В случае выхода управления на Верхний уровень Программе оказываются доступными только слоты [[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 , myScope2 ; A(); function A(x) { // Вход сюда создает новый [[VO]]A ,но не затрагивает [[VO]]Global === ( [[Scope]]A == [ myScope, g==0 ] ) var a; 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 } ; myScope2=B; B(); function B(y,e,e1) { // Вход сюда создает новый [[VO]]B ,но не затрагивает [[VO]]А,[[VO]]Global var b; if (y==1) { a=3; b=3; c=3; eval(e); al( [g, a, b, c,eval(e1) , '<---B( )']); myScope(2); return } ; if (y==2) { al( [g, a, b, c,eval(e1), '-- имеем в B( )']); return } ; C(); function C(z,e,e1) { // Вход сюда создает новый [[VO]]С ,но не затрагивает [[VO]]B, [[VO]]А ,[[VO]]Global var c; if (z==1) { a=4; b=4; c=4; al( [g, a, b, c,eval(e1), '<---C( )']); myScope(2); return } ; if (z==2) { al( [g, a, b, c, eval(e1), '-- имеем в 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,,,,-- имеем в C( ) // <-исходное состояние [[Scope]]'а' Замыкания myScope(2); // Выход на уровень Контекста Global - Полный выход из Контекста Замыкания, В вызываемой функции A // никакие слоты [[Scope]]'a' Замыкания не доступны, кроме [[Scope]]A === [[VO]]Global слотов (ни а ни b не изменить) // 0,2,2,2,<---A( ) // 0,,,,-- имеем в C( ) A(1); // Выход на Уровень Контекста А - Частичный выход из Контекста Замыкания, // в вызываемой B() будут доступны только слоты [[Scope]]'a' Замыкания для [[Scope]]B ( a можем изменить, b -нет ) // 0,3,3,3,<---B( ) // 0,3,,,-- имеем в C( ) // 0,3,3,1,-- имеем в C( ) для вызова C(2) вместо myScope(2),т.е. b меняем ! B(1); // Выход на уровень Контекста B, Нет выхода из Конекста Замыкания, // в вызываемой С() будут доступны все слоты [[Scope]]'a' Замыкания для [[Scope]]C (a и b можно изменить) C(1); // 0,4,4,4,<---C( ) // 0,4,4,,-- имеем в C( ) return; // Выход на уровень Контекста B }; return ; // Выход на уровень Контекста A }; return ; // Выход на уровень Контекста Global - Полный выход из Контекста Замыкания }; al('-----------Как Разные Замыкания могут общаться через пересекающиеся слоты своих СкоповЗамыкания. ---------------------'); al([g,a,b,c,'--имеем в Global как нагрузку от некоторых первичных присваиваний во внутренних функциях ']); // 0,4,2,3,--имеем в Global myScope2(2); // 0,4,,3,-- имеем в B( ) - в СкопеЗамыкания B имеем тот же a , что и myScope(2); // 0,4,4,,-- имеем в C( ) в СкопеЗамыкания C (но переменной b из СкопаЗамыкания С в СкопеЗамыкания B нет) myScope2(1,'var ee=11'); // 0,3,3,3,<---B( ) // 0,3,4,,-- имеем в C( ) //myScope(2,1,'ee'); // ee НЕ ОПРЕДЕЛЕН в C !!! EVAL не меняет слоты Контекста Замыкания ! al([g,a,b,c,'--имеем в Global как нагрузку от некоторых первичных присваиваний во внутренних функциях ']); // 0,4,2,3,--имеем в Global |
Цитата:
Вы упорно пытаетесь перевести общепринятую логику стандарта на птичий язык ньюба, где происходит "установка Защитника(Телохранителя)", где этим "Защитником является переменная Замыкания", где происходит некий "частичный выход из Контекста Замыкания" и так далее. Предположу, что эти ассоциации помогают вам вникать в суть вещей, но повторюсь - примеры простейшие, никаких в них нет странностей, сверхъестественного, начните, наконец, изучать стандарт и стараться разговаривать на его языке. Что ж мы воду толчём в ступе... |
Часовой пояс GMT +3, время: 03:07. |