Контексты исполнения
- 10 Контексты исполнения
-
Когда управление передаётся выполняемому коду на ECMAScript, осуществляется вход в контекст исполнения. Активные контексты выполнения логически формируют стек. Верхним контекстом выполнения в этом логическом стеке является текущий контекст исполнения.
- 10.1 Определения
- 10.1.1 Объекты типа Function
-
Существуют две разновидности объектов типа Function:
- Программные функции определены в исходном тексте при помощи ОбъявленияФункции или создаются динамически при помощи ВыраженияФункции или при помощи встроенного объекта Function в качестве конструктора.
- Внутренние функции являются встроенными объектами языка, например parseInt и Math.exp. Конкретная реализация также может предоставлять свои специфические внутренние функции, не описанные в данной спецификации. Эти функции не содержат исполняемого кода, определяемого в грамматике ECMAScript, поэтому они исключены из данного рассмотрения контекстов выполнения.
- 10.1.2 Типы исполняемого кода
-
Существует три типа исполняемого кода на ECMAScript:
- Глобальный код - исходный текст, который обрабатывается как Программа ECMAScript. Глобальный код конкретной Программы не включает в себя тех частей исходного текста, которые распознаются как ТелоФункции.
- Eval-код - исходный текст, передаваемый во встроенную функцию eval. Точнее, если параметр встроенной функции eval является строкой, он обрабатывается как Программа ECMAScript. Eval-код для конкретного вызова eval является глобальной частью кода, переданного в строковом параметре.
- Код функции - исходный код, который распознаётся как часть ТелаФункции. Код функции для конкретного ТелаФункции не включает в себя тех частей исходного текста, которые распознаются как части вложенных ТелФункций. Код функции также обозначает исходный текст, передаваемый встроенному объекту Function, когда он используется в качестве конструктора. Строго говоря, последний параметр, переданный конструктору Function, преобразовывается в строку и обрабатывается как ТелоФункции. Если более чем один параметр передаётся конструктору Function, все параметры кроме последнего преобразовываются в строки и конкатенируются вместе с использованием запятых в качестве разделителя. Результирующая строка интерпретируется как СписокФормальныхАргументов для ТелаФункции, определённого последним параметром. Код функции для конкретного экземпляра Function не включает в себя тех частей исходного текста, которые распознаются как части вложенных ТелФункций.
- 10.1.3 Инстанциация (создание) переменных
-
Для каждого контекста выполнения имеется связанный с ним объект переменных. Переменные и функции, определённые в исходном тексте, добавляются в качестве свойств объекта переменных. Для кода функции параметры добавляются как свойства объекта переменных.
Какой именно объект используется в качестве объекта переменных и какими из атрибутов обладают его свойства - зависит от типа кода, но остальная часть поведения является общей. При входе в контекст выполнения свойства привязываются к объекту переменных в следующем порядке:
- Для кода функции: для каждого формального аргумента, определённого в СпискеФормальныхАргументов, создать свойство объекта переменных, название которого является Идентификатором и атрибуты которого определены типом кода. Значения параметров передаются вызывающим кодом как аргументы метода [[Call]]. Если вызывающий код передаёт меньше параметров, чем было указано формальных параметров, оставшиеся формальные параметры имеют значение undefined. Если два или больше формальных параметра имеют одинаковое имя и, таким образом, ссылаются на одно и то же свойство, то соответствующее свойство получает значение, переданное для последнего параметра с таким именем. Если значение последнего параметра не было указано при вызове, значением свойства становится undefined.
- Для каждого ОбъявленияФункции в коде по ходу исходного текста, создать свойство объекта переменных с именем Идентификатора, указанного в ОбъявленииФункции, значение которого является результатом создания объекта Function, описанного в разделе 13, и атрибуты которого определяются типом кода. Если в объекте переменных уже есть свойство с таким именем, заменить его значение и атрибуты. Семантически этот шаг должен следовать за созданием свойств для СпискаФормальныхАргументов.
- Для каждого ОбъявленияПеременной или ОбъявленияПеременнойБезIn в исходном коде, создать свойство в объекте переменных с именем Идентификатора, указанного в ОбъявленииПеременной или ОбъявленииПеременнойБезIn, значение которого равно undefined и атрибуты которого определяются типом кода. Если в объекте переменных уже существует свойство с именем объявленной переменной, значение свойства и его атрибуты не изменяются. Семантически этот шаг должен следовать за созданием свойств для СпискаФормальныхАргументов и ОбъявленийФункций. В частности, если имя объявляемой переменной совпадает с именем объявленной функции или формальным параметром, объявление переменной не влияет на существующее свойство.
- 10.1.4 Иерархия областей видимости и разрешение идентификаторов
-
Для каждого контекста выполнения имеется связанная с ним иерархия областей видимости. Иерархия областей видимости - это список объектов, в которых производится поиск при определении значения Идентификатора. Когда управление входит в контекст выполнения, создаётся иерархия областей видимости и сразу заполняется начальным набором объектов, зависящим от типа кода. Во время исполнения кода в контексте исполнения на иерархию областей видимости влияют только инструкции with (см. раздел 12.10) и конструкции catch (см. раздел 12.14).
Во время выполнения получение значения синтаксического нетерминала ПервичноеВыражение : Идентификатор производится по следующему алгоритму:
1. Получить следующий объект в иерархии областей видимости. Если такого объекта нет, переход на шаг 5.
2. Вызвать метод [[HasProperty]] у Результата(1), передавая Идентификатор в качестве имени свойства.
3. Если Результат(2) равен true, вернуть значение типа Reference, базовым объектом которого является Результат(1), а именем свойства - Идентификатор.
4. Переход на шаг 1.
5. Вернуть значение типа Reference, базовым объектом которого является null, а именем свойства - Идентификатор.
Результатом получения значения идентификатора всегда является значение типа Reference, имя свойства которого совпадает с именем идентификатора.
- 10.1.5 Глобальный объект
-
Существует единственный общий глобальный объект (см. раздел 15.1), который создаётся прежде, чем управление приходит в какой-либо из контекстов выполнения. Первоначально у глобального объекта есть следующие свойства:
- Встроенные объекты, такие как Math, String, Date, parseInt и т.д. Они обладают атрибутами { DontEnum }.
- Дополнительные свойства, определённые средой. Они могут включать в себя свойства, значением которых является сам объект. Например, в объектной модели документа HTML свойство window глобального объекта представляет собой сам глобальный объект.
Когда управление входит в контексты выполнения, по ходу исполнения кода на ECMAScript к глобальному объекту могут добавляться новые свойства и меняться старые.
- 10.1.6 Объект активации
-
Когда управление входит в контекст выполнения кода функции, объект, называемый объектом активации, создаётся и связывается с контекстом выполнения. Объект активации инициализируется с именем свойства arguments и атрибутами { DontDelete }. Начальным значением этого свойства является описываемый ниже объект аргументов.
Объект активации затем используется в качестве объекта переменных для инстанциации переменных.
Объект активации является механизмом, используемым исключительно в целях определения спецификации. Для программы на ECMAScript невозможно получить доступ к объекту активации. Она может получать доступ к полям этого объекта, но не к самому объекту. Когда операция вызова применяется к значению Reference, базовым объектом которого является объект активации, в качестве значения this в таком вызове используется null.
- 10.1.7 This
-
Для каждого активного контекста выполнения существует связанная с ним переменная this. Значение this зависит от вызывающего и от типа выполняемого кода и определяется, когда управление входит в контекст выполнения. Значение this, связанное с контекстом выполнения, является неизменяемым.
- 10.1.8 Объект аргументов
-
Когда управление входит в контекст выполнения кода функции, создаётся объект аргументов, который инициализируется следующим образом:
- Значение встроенного свойства [[Prototype]] для объекта аргументов равно первоначальному объекту-прототипу Object, т.е. тому, который представляет собой первоначальное значение Object.prototype (см. раздел 15.2.3.1).
- Создаётся свойство с именем callee и атрибутами { DontEnum }. Первоначальное значение этого свойства - объект Function, выполнение которого производится в данный момент. Это позволяет анонимным функциям быть рекурсивными.
- Создаётся свойство с именем length и атрибутами { DontEnum }. Начальным значением этого свойства является число реальных значений аргументов, переданное при вызове.
- Для каждого неотрицательного числа arg, меньшего значения свойства length создаётся свойство с именем ToString(arg) и атрибутом { DontEnum }. Начальным значением этого свойства является реальное значение соответствующего аргумента, переданное при вызове. Первое реальное значение аргумента соответствует arg = 0, второе - arg = 1 и так далее. В том случае, когда arg меньше количества формальных параметров объекта Function, значение свойства является общим с соответствующим свойством объекта активации. Это означает, что изменение данного свойства изменяет соответствующее значение свойства у объекта активации и наоборот.
- 10.2 Вход в контекст исполнения
-
Каждый вызов функции или конструктора входит в новый контекст исполнения, даже если функция вызывает себя рекурсивно. Каждый возврат (return) выходит из контекста исполнения. Брошенное исключение, если оно не поймано, тоже может выйти из одного или более контекстов исполнения.
Когда управление входит в контекст исполнения, создаётся и инициализируется иерархия областей видимости, происходит инстанциация переменных и определяется значение this.
Инициализация иерархии областей видимости, инстанциация переменных и определение значения this зависят от типа кода, в который производится вход.
- 10.2.1 Глобальный код
-
- Создаётся иерархия областей видимости, которая после инициализации содержит только один глобальный объект и никаких более.
- Инстанциация переменных производится при помощи глобального объекта в качестве объекта переменных, с использованием атрибутов свойств { DontDelete }.
- Значением this является глобальный объект .
- 10.2.2 Eval-код
-
Когда управление входит в контекст выполнения для eval-кода, для определения иерархии областей видимости, объекта переменных и значения this используется предыдущий активный контекст исполнения, называемый вызывающим контекстом. Если вызывающего контекста не существует, инициализация иерархии областей видимости, инстанциация переменных и определение значения this производятся так же, как и для глобального кода.
- Иерархия областей видимости при инициализации содержит те же объекты и в том же порядке, что и иерархия областей видимости вызывающего контекста. При этом включаются объекты, добавленные в иерархию областей видимости вызывающего контекста инструкциями with и конструкциями catch.
- Инстанциация переменных производится при помощи объекта переменных вызывающего контекста и пустых атрибутов свойств.
- Значение this совпадает со значением this для вызывающего контекста.
- 10.2.3 Код функции
-
- Иерархия областей видимости при инициализации содержит объект активации, за которым следуют объекты иерархии областей видимости, сохранённой в свойстве [[Scope]] объекта типа Function.
- Инстанциация переменных производится при помощи объекта активации в качестве объекта переменных и с использованием атрибутов свойств { DontDelete }.
- Значение this передаётся вызывающим. Если значение this, переданное вызывающим, не является объектом (заметим, что null - не объект), то значением this является глобальный объект.
|