Специально для работы с рекурсией в JavaScript существует особое расширение функциональных выражений, которое называется «Named Function Expression» (сокращённо NFE) или, по-русски, «именованное функциональное выражение».
Named Function Expression
Обычное функциональное выражение:
var f = function(...) { /* тело функции */ };
Именованное с именем sayHi:
var f = function sayHi(...) { /* тело функции */ };
Что же это за имя, которое идёт в дополнение к f, и зачем оно?
Имя функционального выражения (sayHi) имеет особый смысл. Оно доступно только изнутри самой функции (f).
Это ограничение видимости входит в стандарт JavaScript и поддерживается всеми браузерами, кроме IE8-.
Например:
Кроме того, имя NFE нельзя перезаписать:
В режиме use strict код выше выдал бы ошибку.
Как правило, имя NFE используется для единственной цели – позволить изнутри функции вызвать саму себя.
Пример использования
NFE используется в первую очередь в тех ситуациях, когда функцию нужно передавать в другое место кода или перемещать из одной переменной в другую.
Внутреннее имя позволяет функции надёжно обращаться к самой себе, где бы она ни находилась.
Вспомним, к примеру, функцию-факториал из задачи Вычислить факториал:
Попробуем перенести её в другую переменную g:
Ошибка возникла потому что функция из своего кода обращается к своему старому имени f. А этой функции уже нет, f = null.
Для того, чтобы функция всегда надёжно работала, объявим её как Named Function Expression:
Как мы говорили выше, в браузере IE до 9 версии имя NFE видно везде, что является ошибкой с точки зрения стандарта.
...Но на самом деле ситуация ещё забавнее. Старый IE создаёт в таких случаях целых две функции: одна записывается в переменную f, а вторая – в переменную factorial.
Например:
Все остальные браузеры полностью поддерживают именованные функциональные выражения.
arguments.calleeЕсли вы давно работаете с JavaScript, то, возможно, знаете, что раньше для этой цели также служило специальное значение arguments.callee.
Если это название вам ни о чём не говорит – всё в порядке, читайте дальше, мы обязательно обсудим его в отдельной главе.
Если же вы в курсе, то стоит иметь в виду, что оно официально исключено из современного стандарта. А NFE – это наше настоящее.
Итого
Если функция задана как Function Expression, ей можно дать имя.
Оно будет доступно только внутри функции (кроме IE8-).
Это имя предназначено для надёжного рекурсивного вызова функции, даже если она записана в другую переменную.
Обратим внимание, что с Function Declaration так поступить нельзя. Такое «специальное» внутреннее имя функции задаётся только в синтаксисе Function Expression.
Комментарии
<code>, для нескольких строк кода — тег<pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen...)