Статья, в которой рассмотрим ещё один способ создания функции - посредством выражения определения. Кроме этого разберём отличие этого способа объявления функции от традиционного.

Создание функции посредством выражения определения

В JavaScript создать функцию можно не только с помощью традиционного способа (объявления - Traditional Declarations), но и посредством выражения определения (Definition Expressions). Этот способ определения функции в некоторых источниках носит названия функционального литерала.

Основная идея Definition Expressions заключается в том, что описание функции используют в качестве значения некоторой переменной или выражения.

Сравнение синтаксиса функции, созданной традиционным образам и с помощью выражения определения
Сравнение синтаксиса функции, созданной традиционным образам и с помощью выражения определения

Например, переменная sum будет содержать описание функции, которая будет выводить в консоль сумму 2 чисел, указанных в качестве параметра.

var sum = function(num1,num2) {
  return console.log(num1+num2);
};

Вызов функции, созданной на основании выражения определения, осуществляется по имени переменной.

//например, вызовем функцию, которая содержится в переменной sum и передадим ей 2 аргумента.
sum(7,4);

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

Обратите внимание на то, что JavaScript позволяет использовать в синтаксисе функции, которая создана как выражение определения, имя. Но, это имеет смысл только тогда, когда к ней необходимо обратиться внутри её же тела. Например, при написании рекурсивных функций. Другого применения данная возможность не даёт, так как обратиться к функции, определённой таким образом, за её пределами, по имени нельзя.

Например, создадим функцию для вычисления факториала, указанного в качестве параметра числа:

var factorial = function fact(num) {
  if (num<=1) return 1; 
  else return num = num*fact(num-1);
};
// выведем в консоль результат вызова функции factorial(5)
console.log(factorial(5));

Этот код определяет функцию и сохраняет ссылку на неё в переменную factorial. Для вызова функции внутри этой функции используем имя fact. Обратите внимание, что обратиться к функции вне её тела по имени fact нельзя, для этого необходимо использовать переменную factorial.

Но и в этом случае можно обойтись без имени, т.к. JavaScript позволяет вызвать функцию внутри своего тела с помощью свойства callee объекта arguments.

var factorial = function(num) {
  if (num<=1) return 1; 
  else return num = num*arguments.callee(num-1);
};
// выведем в консоль результат вызова функции factorial(5)
console.log(factorial(5));

JavaScript - Самовызывающаяся функция

Функцию, определённую посредством выражения определения, можно вызвать немедленно. Для этого после тела функции необходимо поставить круглые скобки и указать в них при необходимости аргументы.

Например, вызовем функцию sum немедленно со значениями параметров 7 и 4.

var sum = function(num1,num2) {
  return console.log(num1+num2);
}(7,4);

Процесс немедленного вызова функции иногда называют инициализацией или инстанциацией функции.

Выражение определения функции очень часто используют, если необходимо её выполнить один раз и немедленно. Для этого даже можно не использовать переменную, а сразу написать вычисляемое выражение, т.е. обернуть определение анонимной функции в круглые скобки.

(function(num1,num2) {
  return console.log(num1+num2);
}(7,4));

Отличия Function Declaration и Function Expression

Основные различия между функциями Function Declaration и Function Expression представим в следующей таблице:

Function Declaration Function Expression
Браузер (интерпретатор JavaScript) считает функцию - Function Declaration, если она расположена в основном потоке кода (не является частью какого-либо выражения). Браузер находит функцию как Function Expression, если она размещена в составе некоторого выражения.
При объявлении функции этим способом, переменная, по которой происходит обращение к ней, создаётся автоматически.
function square(a) {
   return a*a;
}
// обращение к функции
console.log(square(5));
Для обращения к функции необходимо создать переменную и сохранить в неё ссылку на эту функцию.
var square = function(a) {
  return a*a;
}
// обращение к функции
console.log(square(5));
Инициализируется до выполнения кода (в соотвествующей области видимости). Данное действие ещё называют поднятием или hoisting (хойстингом). Такие функции можно вызывать до объявления.
// вызываем функцию до её объявления
console.log(square(7));
function square(a) {
  return a*a;
}
Функции Function Expression нельзя использовать до объявления. Поднимается только сама переменная.
// ошибка при вызове функции
console.log(square(7));
var square = function(a) {
  return a*a;
}

В этом случае происходит следующее:

var square;
console.log(square(7)); // но на этом этапе переменная square имеет значение undefined
square = function(a) {
  return a*a;
}
При использовании use strict функция, объявленная как Function Declaration, будет видна только внутри блока, в котором она объявлена.
'use strict';
if (true) {
  function sum(a,b,c) {
    return a+b+c;
  }
  console.log(sum(10,20,10));
}
// ошибка доступа к функции sum
console.log(sum(4,5,4));
В отличие от Function Declaration, доступ к функции можно получить вне блока, в котором она создана:
'use strict';
if (true) {
  var sum = function (a,b,c) {
    return a+b+c;
  }
  console.log(sum(10,20,10));
}
// имеем доступ к функции sum 
console.log(sum(4,5,4));
Функцию, объявленную как Function Declaration вызвать немедленно нельзя.
Для того чтобы это осуществить необходимо функцию сделать частью выражения, например, обернуть её в круглые скобки. После этого функция будет считаться частью выражения (Function Expression) и её можно вызвать немедленно.
Например:
var sum = (function sum(a,b,c) {
  return a+b+c;
})(5,6,7);
console.log(typeof sum); // number
console.log(sum); // number
Функцию, объявленную как Function Expression можно вызвать немедленно.
var sum = function (a,b,c) {
  return a+b+c;
}(5,6,7);
console.log(typeof sum); // number
console.log(sum); // number
При этом переменная sum (в данном случае) содержит уже не ссылку на функцию, а её результат (в этом примере число).

Вывод: Способ объявления функции с помощью выражения определения позволяет использовать функцию как переменную. Данная возможность языка JavaScript является очень интересной и позволяет создавать более гибкие сценарии.