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

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

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

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


person praks5432    schedule 27.07.2015    source источник
comment
На самом деле это так, см.: developer.mozilla.org /en-US/docs/Web/JavaScript/Reference/   -  person heartyporridge    schedule 28.07.2015
comment
Я думаю, что это именованное функциональное выражение, а не объявление функции. Областью действия имени является только тело определяемой функции, а не окружающая функция.   -  person Barmar    schedule 28.07.2015
comment
Это как var foo = function f() {};.   -  person Barmar    schedule 28.07.2015


Ответы (3)


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

Это создает функциональное выражение named:

if(function f(){})

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

О выражениях именованных функций см. https://kangax.github.io/nfe/#named-expr. :

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

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

x += typeof f;

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

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

alert(typeof f);     //undefined

person Rick Hitchcock    schedule 27.07.2015

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

Цитирование Kangax:

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

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

person Felipe Skinner    schedule 27.07.2015
comment
Действительно ли Block относится к части if ( ) или части { body } после нее? - person Barmar; 28.07.2015
comment
Я почти уверен, что сам if ( ) тоже считается блоком... но не на 100% :( - person Felipe Skinner; 28.07.2015
comment
так как вы можете объявить переменную внутри for ( ) и она действительна только внутри своего блока... Я думаю, это работает так же - person Felipe Skinner; 28.07.2015
comment
Итак... почему приведенное выше произвело 1undefined? (как ни странно, я взял пример с perfectionkills.com/whats-wrong-with -extending-the-dom, что написал kangax) - person praks5432; 28.07.2015
comment
Если вы посмотрите на код перед цитатой, похоже, что я писал. Он говорит о if (foo) { function bar() {...} } - person Barmar; 28.07.2015
comment
Да, функция в коде ОП не находится в блоке , который определяется как { StatementList }. - person 1983; 28.07.2015

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

person 1983    schedule 28.07.2015