12.04.2009, 19:35
|
...
|
|
Регистрация: 09.03.2008
Сообщений: 216
|
|
Сообщение от kefi
|
контекстом функции
|
Контекст исполнения (execution context) - некая абстракция, изолирующая одну часть исполняемого кода от других частей в зависимости от того, что это за код. Исполняемый код лексически делится на три части - Global code, Function code, Eval code, отсюда и три вида контекста исполнения, по которым бродит js-интерпретатор. Контексты формируют стек, запустили сам скрипт - вошли в глобальный контекст, запустили функцию - вошли в контекст этой функции, запустили вложенную функцию - вошли в контекст вложенной функции, вернули что-то из вложенной - вышли из контекста вложенной и вернулись в контекст внешней, вернули что-то из внешней - вышли из контекста внешней и вернулись в глобальный контекст, отработал сам скрипт - вышли из глобального контекста... В любой точке сущестует один единственный активный/работающий контекст исполнения.
Сообщение от kefi
|
объектом переменных
|
Если говорить об именах, то js - это мир свойств. Переменные, параметры и имена объявленных функций должны стать свойствами некого объекта. Специально для них создаё(ю)тся объект(ы).
Сообщение от kefi
|
[[scope]] функции
|
тест
|
|
13.04.2009, 00:19
|
Кандидат Javascript-наук
|
|
Регистрация: 12.03.2009
Сообщений: 148
|
|
2 Zeroglif >
мда, что-то мутно там.
Мог бы кто понятно объяснить эти [[scope]], VO, контекст и иже с ними (какие-то, оказывается, еще спец объекты бывают ... ) , какие из этих объектов когда создаются, что они содержат и какие из них свойствами каких являются :
- при доRUN-time'оых FD определениях функций ,
- при FE определениях функций ,
- при вызове функций ?
Последний раз редактировалось kefi, 13.04.2009 в 00:22.
|
|
13.04.2009, 12:11
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Вообще, там достаточно информации было, но попробую ещё проще; по частям, чтобы "уварилось". Начнём с 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:
Эм.. Оказывается, я уже в этой теме писал почти тоже самое.
Последний раз редактировалось Dmitry A. Soshnikov, 13.04.2009 в 12:34.
Причина: поправки, опечатки
|
|
13.04.2009, 12:59
|
Кандидат Javascript-наук
|
|
Регистрация: 12.03.2009
Сообщений: 148
|
|
Сообщение от Dmitry A. Soshnikov
|
Если здесь всё понятно, и есть желание дальше изучать, можно будет продолжить.
|
Да, VO, вроде понятно, но возник еще объект активации AO...
а еще есть arguments, [[scope]] , etc ... Да, и еще бы понять, чьи они свойства - если функции , то в глобальном контексте если находимся - тогда чьи ?
Последний раз редактировалось kefi, 13.04.2009 в 13:03.
|
|
13.04.2009, 23:26
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от kefi
|
но возник еще объект активации AO...
|
Activation object (Объект активации, AO) касается только контекста исполнения типа "Функция".
Кстати, в предыдущем посте, говоря о VO, в большей мере имелся в виду VO функции.
AO создаётся при входе в контекст функции и инициализируется свойством arguments, значением которого является Arguments object (Объект аргументов, обозначим ArgO, чтобы не путать с AO):
AO = {
arguments: <ArgO>
};
Далее, этот AO становится ничем иным как VO. Поэтому, говоря о VO в контексте типа "функция", можно использовать и терминологию AO, т.к. здесь VO === AO. Образно в предыдущем посте (чтобы не перегужать и не приплетать arguments) я назвал это "наследуется", физически же, это тот же самый объект.
Говоря о VO в глобальном контексте, - сам глобальный объект является VO (в браузере - window).
Сообщение от kefi
|
а еще есть arguments,
|
Arguments object (ссылка выше) - объект, находящийся в VO/AO функции; содержит свойства:
- 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);
Сообщение от kefi
|
Да, и еще бы понять, чьи они свойства - если функции , то в глобальном контексте если находимся - тогда чьи ?
|
Если код входит в контекст функции, то это свойства функции. Если мы находимся в глобальном коде, то сам глобальный объект - есть VO.
Если всё понятно, можно будет продолжить про [[Scope]].
Последний раз редактировалось Dmitry A. Soshnikov, 14.04.2009 в 11:32.
Причина: опечатки
|
|
14.04.2009, 23:46
|
Кандидат Javascript-наук
|
|
Регистрация: 12.03.2009
Сообщений: 148
|
|
Я понял так , еще немного допридумал, чтобы было логичнее, проверьте что не так :
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]].
|
"Огласите весь список, пожалуйста."
Последний раз редактировалось kefi, 14.04.2009 в 23:50.
|
|
15.04.2009, 00:31
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от kefi
|
Для глобального контекста :
VO===Global (где Global - встроенный глобальный объект) нашпиговывается ДО run-time слотами, которые по мере работы программы могут менять свои значения, но не свое количество или имена !
|
До исполнения, если встречаются: var и FD. Всё остальное (например, a = 10 (без var), либо явно - window.a = 10) - создаётся в runtime'e (и слот и его значение). Поэтому, Global свободно может менять свои слоты и значения этих слотов в runtime'e.
Сообщение от kefi
|
Если не было входа управления в контекст функции, то не существует для нее никакого ни VO, ни AO.
|
Да, так. Однако, [[Scope]] в функции зашит изначально и навсегда, не важно, будет ли запущена функция или нет.
Сообщение от kefi
|
Если управление вошло во внутренний контекст функции F , то ДО ее выполнения для этой функции создается свой VO', при этом выполняются след шаги :
|
Да.
Сообщение от kefi
|
F.VO=AO;
|
Можно и так, для удобства (абстрактно) обозначить.
Сообщение от kefi
|
delete F.VO
|
Да, только, если не было замыкания, тогда F.VO сохранится в [[Scope]] внутренней функции (т.е. не будет удалён, пока на него есть ссылка).
Сообщение от kefi
|
"Огласите весь список, пожалуйста."
|
[[Scope]] - это иерархическая цепь Объектов переменных (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 в цепи, стоящие иерархически выше - остаются в памяти.
Последний раз редактировалось Dmitry A. Soshnikov, 15.04.2009 в 14:11.
|
|
15.04.2009, 01:33
|
Кандидат Javascript-наук
|
|
Регистрация: 12.03.2009
Сообщений: 148
|
|
2 Dmitry A. Soshnikov >
Все яснее и яснее, Я сам-то мучился с этими терминами, понимал для себя только , что есть внешний контекст для каждой функции и внутренний. И как это все Вы поняли из ECMA спецификации , ума не приложу ...
Кстати контекст, как я сейчас понимаю, не является термином обозначающим некий объект, это чисто лексический контекст для текста функции или какого-ни слова из кода программы ?
Вот правда, еще остается непонятной роль AO - вроде как и нни к чему он , да еще какой-то непонятныйц остается спец объект из Вашей ссылки выше.
Цитата:
|
При return d; остаётся ссылка на [[Scope]](d), поэтому все VO в цепи, стоящие иерархически выше - остаются в памяти
|
Хотел уточнить :
- именно на [[Scope]] , т.е. БЕЗ VO функции d ?
- и сохраняются не просто , если возвращается return, как в Вашем примере b() , а если возвращаемое где-то сохранено var q=b() ?
|
|
15.04.2009, 21:43
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от kefi
|
И как это все Вы поняли из ECMA спецификации , ума не приложу ...
|
Несомненно, стоит отметить этого человека - изначально, он помог мне поднять некоторые глубокие аспекты ("Этот человек", только ни в коем случае не считай это за лесть =) я просто благодарен и отдаю должное ). Углубляясь, изучая, дальше сам уже стандарт проштудировал (что и всем советую для профессионального понимания JavaScript).
Сообщение от kefi
|
Кстати контекст, как я сейчас понимаю, не является термином обозначающим некий объект, это чисто лексический контекст для текста функции или какого-ни слова из кода программы ?
|
Да, это абстракное определение, зависящее от типа кода: Global code, Eval code, Function code.
Сообщение от kefi
|
Вот правда, еще остается непонятной роль AO - вроде как и нни к чему он
|
AO - это и есть VO. А VO, в свою очередь, можно тоже считать абстракцией. Физически же, эта абстракция представлена AO (для функции и eval'a) и Global - для Global'a. У Global'a нет arguments, поэтому для функции это назвали AO. Если говорить отстраннённо от JS, можно представить VO - как интерфейс, а AO и Global - как конкретные классы, реализующие этот интерфейс.
Сообщение от kefi
|
да еще какой-то непонятныйц остается спец объект
|
Спец.объект - "анонимный объект", который содержит одно единственное свойство - опциональное имя FE, чтобы FE могла обратиться к себе рекрсивно по имени (помимо arguments.callee):
(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) и, соотвественно, может быть найден.
Здесь ещё можно почитать.
Сообщение от kefi
|
- именно на [[Scope]] , т.е. БЕЗ VO функции d ?
|
update: VO и Scope создаются каждый раз при вызове функции; запоминается только [[Scope]](d).
Сообщение от kefi
|
- и сохраняются не просто , если возвращается return, как в Вашем примере b() , а если возвращаемое где-то сохранено var q=b()
|
Да, конечно, это тоже подразумевалось.
Последний раз редактировалось Dmitry A. Soshnikov, 16.04.2009 в 15:57.
|
|
15.04.2009, 23:52
|
Кандидат Javascript-наук
|
|
Регистрация: 12.03.2009
Сообщений: 148
|
|
Чьим VO? я-то имел ввиду, что VO(d) не сохраняется поскольку НЕ НУЖЕН , т.к. при очередном вызове через замыкание он создается заново .
|
|
|
|