Поднимается ли функция, если она определена в условии 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 является выражением, поэтому у вас есть выражение функции; это не может быть объявление функции. И поэтому он не поднимается, так как только объявления функций.