Прежде чем пользоваться какой-нибудь функцией в JavaScript, её сначала нужно объявить, чтобы среда выполнения кода могла её зарегистрировать, а в случае вызова знала куда пойти её искать.
Тут речь идёт только о новой функции, которая имеет свой уникальный проектный функционал. Имеется ввиду, что в среде выполнения кода она ранее не была объявлена. И это мы не учитываем всевозможные интерфейсы прикладного программирования, которые работают, например, в браузере (которые тоже являются функциями, но которые знает среда). Сюда мы также не относим все стандартные методы хорошо известных объектов JavaScript.
1. Объявление функции через ключевое слово function
Если мы говорим о стандартном Объявлении Функции (Function Declaration), то мы должны знать два производства по стандарту ECMAScript, при помощи которых можно объявить новую функцию. Эти два производства отличаются по сути только присваиванием Идентификатора Привязки (Binding Identifier) для нашей новой функции.
FunctionDeclaration [Yield, Await, Default] :
function BindingIdentifier [?Yield, ?Await] ( FormalParameters [~Yield, ~Await] ) { FunctionBody [~Yield, ~Await] }
FunctionDeclaration [Yield, Await, Default] :
[+Default] function ( FormalParameters [~Yield, ~Await] ) { FunctionBody [~Yield, ~Await] }
function getZ (){}
Идентификатор привязки назвали «getZ»
function (){}
Идентификатор привязки отсутствует, поэтому в таком виде её нельзя использовать в качестве отдельной команды Скрипта.
Но её можно использовать при передаче параметров в какую-нибудь другую функцию
Безымянная функция
Попытка объявления безымянной функции на верхнем «уровне видимости» нашего Скрипта, приведёт к синтаксической ошибке:
То есть в качестве отдельной команды нельзя использовать безымянный вид объявления функции.
Но его можно использовать, например, в методах массивов, в качестве объявления функции обратного вызова.
Метод map() в качестве первого параметра ожидает получить какую-нибудь функцию, при помощи которой он будет модифицировать все элементы массива. И ему абсолютно плевать, будет это ссылка на объявленную ранее функцию (до вызова map) или же это будет непосредственное объявление безымянной функции в качестве параметра для метода map().
Важно отметить то, что в обоих примерах мы используем ключевое слово «function«, которое является Зарезервированным Словом (Reserved Word) в JavaScript. Также у нас в обоих случаях встречаются:
- Блок для аргументов (для того что планируем передавать)
- Блок для тела функции (чтобы знать что делать с аргументами)
Оба блока пустые. Это сделано специально для того, чтобы понимать самое минимальное требование, необходимое для объявления функции. В наших примерах обе функции НИЧЕГО не делают, но объявлены.
Браузер и объект Window
Все именованные функции, объявленные через ключевое слово «function» поселяются жить в виде нового свойства для ГЛОБАЛЬНОГО объекта JavaScript. В браузере это объект Window.
2. Объявление стрелочных функций
Важно знать, что кроме обычных функций, можно объявлять и стрелочные функции. Между ними есть пара отличий:
- В случае с функциями-стрелками мы уже не используем Зарезервированное Слово «function«. Оно просто отпадает.
- Функции стрелки по умолчанию предполагают возврат какого-либо значения (оформлено символами =>).
Давайте обратимся к производству стрелочных функций. Оно всего одно т. к. все стрелочные функции являются безымянными.
ArrowFunction [In, Yield, Await] :
ArrowParameters [?Yield, ?Await] [не LineTerminator здесь] => ConciseBody [?In]
Лаконичное Тело оформлено в виде FunctionBody
()=>{}
Лаконичное Тело оформлено в виде ExpressionBody
()=>x
Лаконичное Тело оформлено в виде FunctionBody. Один аргумент можно не покрывать круглыми скобками.
z=>{z+1}
Один аргумент можно покрыть круглыми скобками.
(z)=>{z+1}
Лаконичное Тело оформлено в виде ExpressionBody. Один аргумент можно не покрывать круглыми скобками.
z=>z+1
Один аргумент можно покрыть круглыми скобками.
(z)=>z+1
(q, w)=>{q+w}
(q, w)=>q+w
3. Объявление функции через конструктор класса Function
Function()
new Function()
Синтаксис определения функции
FunctionDeclaration [Yield, Await, Default] :
function BindingIdentifier [?Yield, ?Await] ( FormalParameters [~Yield, ~Await] ) { FunctionBody [~Yield, ~Await] }
[+Default] function ( FormalParameters [~Yield, ~Await] ) { FunctionBody [~Yield, ~Await] }
function BindingIdentifier [~Yield, ~Await] opt ( FormalParameters [~Yield, ~Await] ) { FunctionBody [~Yield, ~Await] }
FunctionBody [Yield, Await] :
FunctionStatementList [?Yield, ?Await]
FunctionStatementList [Yield, Await] :
StatementList [?Yield, ?Await, +Return] opt
Синтаксис Определения Стрелочных Функций
ArrowFunction [In, Yield, Await] :
ArrowParameters [?Yield, ?Await] [не LineTerminator здесь] => ConciseBody [?In]
ArrowParameters [Yield, Await] :
BindingIdentifier [?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList [?Yield, ?Await]
ConciseBody [In] :
[lookahead ≠ {] ExpressionBody [?In, ~Await]
{ FunctionBody [~Yield, ~Await] }
ExpressionBody [In, Await] :
AssignmentExpression [?In, ~Yield, ?Await]
Информационные ссылки
Стандарт ECMAScript — Раздел «15.2 Function Definitions» — https://tc39.es/ecma262/#sec-function-definitions