Ответ 1
ECMAScript 5, текущая официальная спецификация языка JavaScript, не определяет поведение для деклараций функций внутри блоков.
Цитата Kangax:
ФункцияDeclarations разрешена только в Program или FunctionBody. Синтаксически они не могут отображаться в блоке (
{ ... }
) - например, в выраженияхif
,while
илиfor
. Это связано с тем, что Blocks может содержать только выражения, а не SourceElements, которые являются FunctionDeclaration. Если мы тщательно рассмотрим правила производства, мы увидим, что единственный способ выражения, разрешенный непосредственно в блоке, - это когда он является частью ExpressionStatement. Тем не менее, выражение ExpressionStatement явно определено , чтобы не начинаться с ключевого слова "function" , и именно поэтому FunctionDeclaration не может отображаться непосредственно в Statement или Block (обратите внимание, что Block - это всего лишь список операторов).Из-за этих ограничений всякий раз, когда функция появляется непосредственно в блоке (например, в предыдущем примере), она должна быть считаться синтаксической ошибкой, а не объявлением функции или выражением. Проблема в том, что почти ни одна из реализаций, которые я видел, не анализирует эти функции строго по правилам (исключениями являются BESEN и DMDScript). Вместо этого они интерпретируют их проприетарно.
Также стоит процитировать проект ECMAScript 6 - B.3.3. Декларации функций уровня блока. Веб-совместимость. Семантика совместимости:
До шестого издания спецификация ECMAScript не определяла появление FunctionDeclaration как элемента блока Statement StatementList. Тем не менее, поддержка этой формы FunctionDeclaration была допустимым расширением, и большинство разрешенных ECMAScript версий браузера разрешали их. К сожалению, семантика таких объявлений отличается от этих реализаций. [...]
Поскольку ES5 не определяет поведение для деклараций функций внутри блоков, позволяя использовать проприетарные расширения, технически нет "прав" или "неправильных". Рассмотрим их "неуказанное поведение", которое не переносится в разных средах, совместимых с ES5.
В любом случае их легко переписать в переносимый код:
- Если объявление функции должно быть поднято в верхней части текущей функции/глобальной области? Убедитесь, что объявление функции не находится непосредственно внутри блока.
- Должна ли функция быть объявлена только при выполнении блока? Назначьте выражение функции переменной (
var f = function() {};
). Обратите внимание, что нет подъема, и переменная по-прежнему доступна вне блока (объявленияvar
являются областями с функциональным уровнем).
В соответствии с ECMAScript 6 объявления функций ограничены блоками, поэтому Firefox реализует правильное поведение ES6-мудрый.