Поднимается ли функция, если она определена в условии if?

Итак, предположим, у меня есть что-то вроде этого

var x = 1;
   if (function f(){}) {
     x += typeof f;
   }
   x;

Это выводит "1undefined". Я думал, что это должно иметь вывод "1function", потому что функция f(){} должна была быть поднята над if. Это явно не тот случай - почему? Я думал, что объявления функций и тела всегда были подняты наверх?

3 ответа

Объявления функций подняты. Функциональные выражения не являются.

Это создает выражение именованной функции:

if(function f(){})

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

Относительно выражений именованных функций см. https://kangax.github.io/nfe/:

Важно помнить, что это имя доступно только в области только что определенной функции

Этот код выходит за рамки выражения новой функции, и поэтому f не определено:

x += typeof f;

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

(function f() {
  alert(typeof f);   //function
})();

alert(typeof f);     //undefined

Насколько я знаю, ES5 не определяет поведение для объявлений функций внутри блоков.

Цитирую Кангакс:

Функциональные декларации могут появляться только в Program или FunctionBody. Синтаксически они не могут появляться в блоке ({ ... }) - например, в операторах if, while или for. Это связано с тем, что блоки могут содержать только операторы, а не SourceElements, которым является FunctionDeclaration. Если мы внимательно посмотрим на производственные правила, то увидим, что единственный способ, которым Expression допускается непосредственно в блоке, - это когда он является частью ExpressionStatement. Однако ExpressionStatement явно определен так, чтобы не начинаться с ключевого слова "function", и именно поэтому FunctionDeclaration не может появляться непосредственно внутри оператора или блока (обратите внимание, что блок - это просто список операторов).

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

Объявления функций являются утверждениями. Условная часть оператора if является выражением, поэтому у вас есть выражение функции; это не может быть объявление функции. И поэтому он не поднимается, так как только объявления функций.

Другие вопросы по тегам