Подтвердить что ты не робот

Могут ли декларации функций отображаться внутри операторов в JavaScript?

Пожалуйста, учтите официальную спецификацию ECMAScript как источник вашего ответа, а не документ, опубликованный конкретным поставщиком браузеров. (Я знаю, что Mozilla расширяет свою реализацию JavaScript с помощью "операторов функций".)

Итак, в соответствии с спецификацией ECMAScript, ergo, синтаксическими производством, определенными в ней, это действительно?

if (foo) {
    function x() { return; }
}

Обновление: Мой вопрос также может быть сформулирован так: Может ли производство Statement содержать функцию FunctionDeclaration?

Вывод: Ответ НЕТ.

4b9b3361

Ответ 1

Я не согласен с другими ответами, которые говорят, что это действительно.

В соответствии с спецификацией ECMA-262 5th Edition Blocks может содержать только Statements (Раздел 12.1):

Block :
   { StatementList opt }

StatementList :
   Statement
   StatementList  Statement

Однако спецификация не определяет оператор функции, а только FunctionDeclaration и a FunctionExpression. Спектр идет дальше, чтобы отметить это в Раздел 12:

Известно, что несколько широко используемых реализаций ECMAScript поддерживают использование FunctionDeclaration как Statement. Однако существуют значительные и непримиримые вариации среди реализаций в семантике, применяемых к такому FunctionDeclarations. Из-за этой непримиримой разницы использование FunctionDeclaration как Statement приводит к тому, что код не надежно переносится среди реализаций. Рекомендуется, чтобы реализации ECMAScript либо запрещали это использование FunctionDeclaration, либо выдавали предупреждение, когда такое использование встречается. Будущие выпуски ECMAScript могут определять альтернативные переносные средства для объявления функций в контексте Statement.

Для дальнейшего чтения вам также может быть интересно узнать comp.lang.javascript FAQ Раздел 4.2:

4.2 Что такое инструкция функции?

Оператор функции term широко и ошибочно используется для описания FunctionDeclaration. Это вводит в заблуждение, поскольку в ECMAScript a FunctionDeclaration не является Statement; есть места в программе, где разрешен Statement, но FunctionDeclaration нет. Чтобы добавить к этой путанице, некоторые реализации, в частности Mozillas ', предоставляют расширение синтаксиса, называемое оператором функций. Это разрешено в соответствии с разделом 16 ECMA-262, издания 3 и 5.

Пример нестандартной функции:

// Nonstandard syntax, found in GMail source code. DO NOT USE.
try {
  // FunctionDeclaration not allowed in Block.
  function Fze(b,a){return b.unselectable=a}
  /*...*/
} catch(e) { _DumpException(e) }

Код, который использует оператор функции, имеет три известные интерпретации. Некоторые реализации выполняют Fze как выражение, в порядке. Другие, в том числе JScript, оценивают Fze при вводе контекста выполнения, в котором он появляется. Другие же, в частности DMDScript и стандартная конфигурация BESEN, бросают SyntaxError.

Для последовательного поведения во всех реализациях не используйте инструкцию функции; используйте вместо этого FunctionExpression или FunctionDeclaration.

Пример FunctionExpression (действительный):

var Fze;
try {
  Fze = function(b,a){return b.unselectable=a};
  /*...*/
} catch(e) { _DumpException(e) }

Пример FunctionDeclaration (действительный):

// Program code
function aa(b,a){return b.unselectable=a}

Ответ 2

Я не уверен, как это прочитать, но ECMA-262 V5 говорит следующее:

ПРИМЕЧАНИЕ. Известно, что несколько широко используемых реализаций ECMAScript поддерживают использование FunctionDeclaration в качестве Statement. Однако существуют существенные и непримиримые вариации среди реализаций в семантике, применяемых к таким функциям. Из-за этих непримиримых различий использование FunctionDeclaration в качестве заявления приводит к тому, что код не надежно переносится среди реализаций. Рекомендуется, чтобы реализации ECMAScript либо запрещали это использование FunctionDeclaration, либо выдавали предупреждение, когда такое использование встречается. Будущие выпуски ECMAScript могут определять альтернативные переносные средства для объявления функций в контексте Statement.

Если я это правильно понимаю, строго говоря, это означает, что объявления функций не могут быть внутри блоков вообще, потому что блоки могут содержать только выражения.

Я могу быть совершенно не прав в своей интерпретации, хотя - я не знаком с внутренними разработками ECMAScript.

Ответ 3

Нет, это недействительно. Объявления функций могут отображаться только как "исходные элементы", которые либо находятся в глобальной области видимости, либо сразу в пределах другого определения функции, вне всех других операторов. Из спецификации ECMA-262:

FunctionBody: SourceElements

Программа: SourceElements

SourceElement: Statement | FunctionDeclaration

В грамматике нет другого произведения, которое позволяет FunctionDeclaration.

В выражении допускаются только выражения функций:

MemberExpression: FunctionExpression

...

Заявление: ExpressionStatement

Изменить: В последнее время обсуждался другой вопрос. См. Комментарии к этому ответу - раньше я тоже думал, что это может быть допустимым, но в грамматике ясно сказано, что это неверно.

Ответ 4

Из ECMA 262, глава 14

  • Синтаксис программы

Программа: SourceElements SourceElements: SourceElement Элемент SourceElements SourceElement Элемент SourceElement: Statement Семантика FunctionDeclaration

Производственная программа: SourceElements оценивается как следующим образом:

  • Process SourceElements для объявлений функций.

  • Оценить исходные элементы.

  • Результат возврата (2).

Производство SourceElements: Элемент SourceElement обрабатывается для объявления функций следующим образом:

  • Process SourceElement для объявлений функций.

Производство SourceElements: Элемент SourceElement оценивается следующим образом:

  • Оцените исходный элемент.

  • Результат возврата (1).

Производство SourceElements: Элемент SourceElements SourceElement обрабатывается для объявлений функций как следующим образом:

  • Process SourceElements для объявлений функций.

  • Process SourceElement для объявлений функций.

Производство SourceElements: Элемент SourceElements SourceElement оценивается следующим образом:

  • Оценить исходные элементы.

  • Если Result (1) является резким завершением, return Result (1)

  • Оцените исходный элемент.

  • Результат возврата (3).

Источник SourceElement:* Операция обрабатывается для функции * , не предпринимая никаких действий.

Источник SourceElement:* Заявление оценивается следующим образом: *

1. Вычислить выражение.

2. Результат возврата (1).

Источник SourceElement: ФункцияDeclaration обрабатывается для объявления функций следующим образом:

  • Функция FunctionDeclaration для деклараций функций (см. раздел 13).

Источник SourceElement: FunctionDeclaration оценивается как следующим образом:

  • Возврат (обычный, пустой, пустой).

Азнер официально НЕТ. (Шим Видас убедил меня в другом вопросе)

Но исключение не указано ни потому, что оно терпит неудачу, либо работает молча, в зависимости от реализации браузера.

Ответ 5

Версия 5 ECMA-262 говорит, что она не должна быть действительной:

ФункцияДекуляция разрешена только для отображения в программе или FunctionBody. Синтаксически они не могут появляться в Block ({...}) - например, если if, в то время как для заявлений. Это потому что Блоки могут содержать только Заявления, а не SourceElements, которые FunctionDeclaration. Если мы посмотрим на правила производства, мы можем видеть что единственный способ выражения разрешено внутри блока, когда оно часть ExpressionStatement. Однако, ExpressionStatement явно чтобы не начинаться с "функции" ключевое слово, и это именно то, что делает FunctionExpression недействительным как часть заявления или блока (примечание этот Блок является просто списком Отчетность).

Однако, похоже, не многие интерпретаторы подчиняются этому правилу. Kangax говорит, что их следует рассматривать как синтаксические ошибки на на этой странице:

Из-за этих ограничений, всякий раз, когда функция появляется в блоке (например, в предыдущем примере) фактически следует рассматривать как синтаксис ошибка, не объявление функции или выражение. Проблема в том, что почти ни одна из реализаций, которые я видел анализировать эти функции строго за правил (исключениями являются BESEN и DMDScript). Они интерпретируют их в вместо прочего.

Ответ 6

В стандарте ECMAScript FunctionDeclaration не определяется как Statement, а Statement не определяется как способное содержать FunctionDeclaration, поэтому они несовместимы в соответствии со стандартом (хотя на практике каждый интерпретатор JavaScript будет пытаться делать что-то разумное, хотя и не согласующееся между реализациями).

Ответ 7

Да, это действительно.

Все блоки операторов (т.е. все внутри фигурных скобок) могут иметь дополнительные инструкции и декларации, включая функции.

Таким образом, вы можете также определять функции внутри функций и т.д.

Вот ECMA-262 v1 - http://www.mozilla.org/js/language/E262.pdf