Javascript.RU

Определение функции

Update: Более новый материал по этой теме находится по адресу http://es5.javascript.ru.
13 Определение функции

Синтаксис

ОбъявлениеФункции :
function Идентификатор ( СписокФормальныхАргументовопц ){ ТелоФункции }
ВыражениеФункции :
function Идентификаторопц ( СписокФормальныхАргументовопц ){ ТелоФункции }
СписокФормальныхАргументов :
Идентификатор
СписокФормальныхАргументов
, Идентификатор
ТелоФункции :
ЭлементыИсходногоКода

Семантика

Нетерминал ОбъявлениеФункции : function Идентификатор ( СписокФормальныхАргументовопц ){ ТелоФункции } обрабатывается для получения объявления функции следующим образом:

1. Создать новый объект Function согласно разделу 13.2, используя аргументы из СпискаФормальныхАргументовопц и тело из ТелаФункции. Передать иерархию областей видимости текущего контекста исполнения как ОбластьВидимости.

2. Создать свойство текущего объекта переменных (согласно определению в разделе 10.1.3) с именем Идентификатор и значением Результат(1).

Значение нетерминала ВыражениеФункции : function ( СписокФормальныхАргументовопц ){ ТелоФункции } вычисляется по следующей схеме:

1. Создать новый объект Function согласно разделу 13.2, используя аргументы из СпискаФормальныхАргументовопц и тело из ТелаФункции. Передать иерархию областей видимости текущего контекста исполнения как ОбластьВидимости.

2. Вернуть Результат(1).

Значение нетерминала ВыражениеФункции : function Идентификатор ( СписокФормальныхАргументовопц ){ ТелоФункции } вычисляется по следующей схеме

1. Создать новый объект, как он был бы создан выражением new Object().

2. Добавить Результат(1) к началу иерархии областей видимости.

3. Создать новый объект Function согласно разделу 13.2, используя аргументы из СпискаФормальныхАргументовопц и тело из ТелаФункции. Передать иерархию областей видимости текущего контекста исполнения как ОбластьВидимости.

4. Создать свойство в объекте Результат(1). Имя свойства Идентификатор, значение равно Результат(3), атрибуты - { DontDelete, ReadOnly }.

5. Убрать Результат(1) из начала иерархии областей видимости.

6. Вернуть Результат(3).

ЗАМЕЧАНИЕ
ТелоФункции в ВыражениеФункции может ссылаться на Идентификатор, указанный в этом же ВыраженииФункции, чтобы функция могла рекурсивно вызывать себя. Однако в отличие от ОбъявленияФункции Идентификатор ВыраженияФункции не влияет на область видимости, в которой находилось ВыражениеФункции, и не может использоваться для ссылки на функцию из этой области видимости
.

Значение нетерминала ТелоФункции : ЭлементыИсходногоКода вычисляется по следующей схеме:

1. Обработать объявления функций в ЭлементахИсходногоКода.

2. Вычислить значение ЭлементовИсходногоКода.

3. Вернуть Результат(2).

13.1 Определения

Для описания процесса создания объектов функций требуется пара определений:

13.1.1 Тождественные правила грамматики

Два применения грамматического правила для нетерминала ТелоФункции считаются тождественными в одном из следующих случаев:

  • Для обоих случаев ТелоФункции было взято из одного и того же места исходного кода одной и той же программы на ECMAScript. Этот исходный код состоит из глобального кода и содержащихся в нём кодов функций согласно определениям в разделе 10.1.2.
  • Для обоих случаев ТелоФункции было взято из одного и того же места исходного кода, переданного одному и тому же вызову eval (15.1.2.1). Этот исходный код состоит из eval-кода и содержащихся в нём кодов функций согласно определениям в разделе 10.1.2.

ЗАМЕЧАНИЕ
Два случая использования ТелаФункции, полученных путём вызова конструктора Function (см. разделы 15.3.1 и 15.3.2), никогда не считаются тождественными. Аналогично, два случая использования FunctionBody, полученных путём двух разных вызовов eval, никогда не считаются тождественными, даже если этим двум вызовам eval был передан одинаковый аргумент
.

13.1.2 Объединённые объекты

Когда два или более объектов Function объединяются, у них появляются следующие особенности:

  • Каждый раз, когда создаётся или устанавливается не-внутреннее свойство объекта O, соответствующее свойство немедленно создаётся или устанавливается в такое же значение у всех объектов, объединённых с O.
  • Каждый раз, когда удаляется не-внутреннее свойство объекта O, соответствующее свойство немедленно удаляется у всех объектов, объединённых с O.
  • Если объекты O и P объединены, для них операторы сравнения == и === дают положительный результат.
  • Объединение транзитивно и симметрично, так что если объединить объекты O и P и объединить объекты P и Q, то объекты O и Q тоже автоматически окажутся объединёнными.

ЗАМЕЧАНИЕ
Два или более объединённых объекта практически неразличимы, за исключением того, что они могут обладать различными внутренними свойствами. Данная спецификация определяет только одно внутреннее свойство, которое может различаться у таких объектов - [[Scope]]
.

Объединённые объекты используются в данном стандарте как средство для точного описания поведения языка. Не предполагается, что они будут использоваться в качестве образца для практической реализации объектов типа Function. Вместо этого рекомендуется, чтобы реализация самостоятельно определяла случаи, в которых различия в свойствах [[Scope]] у двух или более объединённых объектов типа Function незаметны извне, и повторно использовала в таких случаях один и тот же объект Function вместо создания набора объединённых объектов. Такая оптимизация является разрешённой, поскольку данный стандарт описывает лишь внешнее поведение программ на ECMAScript.

13.2 Создание объектов типа Function

Используя опциональный список аргументов, определённый СпискомФормальныхАргументов, тело, определённое ТеломФункции, и иерархию областей видимости, определённую ОбластьюВидимости, объект типа Function создаётся по следующей схеме:

1. Если уже существует объект E, который был создан предыдущим вызовом алгоритма данного раздела, и этому вызову было передано ТелоФункции, тождественное ТелуФункции, передаваемому сейчас, - переход на шаг 13. (Если существует более одного объекта E, удовлетворяющего этим критериям - конкретная реализация языка может выбрать любой по своему усмотрению.)

2. Создать новый встроенный объект ECMAScript, обозначив его как F.

3. Установить свойство [[Class]] объекта F в "Function".

4. Установить свойство [[Prototype]] объекта F стандартному прототипу объекта Function согласно описанию в разделе 15.3.3.1.

5. Установить свойство [[Call]] объекта F согласно описанию в разделе 13.2.1.

6. Установить свойство [[Construct]] объекта F согласно описанию в разделе 13.2.2.

7. Установить свойство [[Scope]] объекта F равным новой иерархии областей видимости (раздел 10.1.4), содержащей те же объекты, что и ОбластьВидимости.

8. Установить свойство length объекта F равным количеству формальных свойств, указанных в СпискеФормальныхАргументов. Если аргументов указано не было, установить свойство length объекта F равным 0. Этому свойству назначаются атрибуты согласно описанию в разделе 15.3.5.1.

9. Создать новый объект, как он был бы создан выражением new Object().

10. Установить свойство constructor объекта Результат(9) равным F. Этому свойству назначаются атрибуты { DontEnum }.

11. Установить свойство prototype объекта F равным Результату(9). Этому свойству назначаются атрибуты согласно описанию в разделе 15.3.5.2.

12. Вернуть F.

13. Реализация по своему усмотрению может перейти либо на шаг 2, либо на шаг 14.

14. Создать новый встроенный объект ECMAScript, объединённый с E, обозначив его как F. Скопировать все не-внутренние свойства и их атрибуты объекта E в объект F, чтобы не-внутренние свойства объектов E и F были идентичны.

15. Установить свойство [[Class]] объекта F в "Function".

16. Установить свойство [[Prototype]] объекта F стандартному прототипу объекта Function согласно описанию в разделе 15.3.3.1.

17. Установить свойство [[Call]] объекта F согласно описанию в разделе 13.2.1.

18. Установить свойство [[Construct]] объекта F согласно описанию в разделе 13.2.2.

19. Установить свойство [[Scope]] объекта F равным новой иерархии областей видимости (раздел 10.1.4), содержащей те же объекты, что и ОбластьВидимости.

20. Вернуть F.

ЗАМЕЧАНИЕ
Свойство prototype автоматически создаётся для каждой функции с целью обеспечения возможности использования функции в качестве конструктора
.

Шаг 1 позволяет реализации оптимизировать типичный случай функции A, имеющей вложенную независимую функцию B. В этом случае реализация может повторно использовать тот же объект для B, вместо того чтобы создавать каждый раз новый экземпляр при вызове A. Шаг 13 делает эту оптимизацию необязательной; реализация, которая предпочтёт не воспользоваться ей, перейдёт на шаг 2.

Например, для кода

function A() {
   function B(x) {return x* x;} 
   return B; 
}

function C() { 
  return eval("(function(x) {return x* x;})"); 
}

var b1 = A(); 
var b2 = A(); 
function b3(x) {return x* x;} 
function b4(x) {return x* x;} 
var b5 = C(); 
var b6 = C();

реализация может, но не обязана, объединить b1 и b2. Более того, она может использовать для b1 и b2 один и тот же объект, поскольку нет возможности различить их свойства [[Scope]]. С другой стороны, реализация не должна объединять b3 и b4, поскольку их исходные коды не тождественны (согласно 13.1.1). Также реализация не должна объединять b5 и b6, потому что они созданы двумя разными вызовами eval и, таким образом, их исходные коды не тождественны.

На практике скорее всего окажется целесообразным объединять объекты типа Function только в тех случаях, когда реализация может доказать, что различия между их свойствами [[Scope]] не различимы, и в таких случаях можно повторно использовать один объект. Следуя этому принципу, реализация встретит только тривиальный случай объединения объекта с самим собой.

13.2.1 [[Call]]

Когда вызывается свойство [[Call]] объекта F типа Function, предпринимаются следующие шаги:

1. Создать новый контекст исполнения, используя СписокФормальныхАргументов объекта F, переданный список значений аргументов и значение this согласно описанию в 10.2.3.

2. Вычислить значение ТелаФункции.

3. Выйти из контекста исполнения, созданного в шаге 1, восстановив предыдущий контекст исполнения.

4. Если Результат(2). тип равен throw - бросить Результат(2). значение.

5. Если Результат(2). тип равен return - вернуть Результат(2). значение.

6. (Результат(2). тип в данной точке должен равняться normal.) Вернуть undefined.

13.2.2 [[Construct]]

Когда вызывается свойство [[Construct]] объекта F типа Function, предпринимаются следующие шаги:

1. Создать новый встроенный объект ECMAScript.

2. Установить свойство [[Class]] объекта Результат(1) в "Object".

3. Получить значение свойства prototype объекта F.

4. Если Результат(3) является объектом, установить свойство [[Prototype]] Результата(1) равным Результату(3).

5. Если Результат(3) не является объектом, установить свойство [[Prototype]] Результата(1) равным стандартному прототипу объекта Object согласно описанию в разделе 15.2.3.1.

6. Вызвать свойство [[Call]] объекта F, указав Результат(1) в качестве значения this и передав список аргументов, переданный вызову [[Construct]], в качестве значений аргументов.

7. Если Тип(Результата(6)) - Object, вернуть Результат(6).

8. Вернуть Результат(1).


Автор: Гость (не зарегистрирован), дата: 6 марта, 2012 - 23:43
#permalink

Прекрасный материал, спасибо за ваши старания!


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
16 + 4 =
Введите результат. Например, для 1+3, введите 4.
 
Текущий раздел
Поиск по сайту
Реклама
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Последние комментарии
Последние темы на форуме
Forum