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

Что такое функция?

Функция — это некоторый фрагмент кода, который можно описать один раз, а затем вызвать на выполнение в разных частях программы какое-угодно число раз.

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

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

В результате такая программа становится более структурированной. В неё более просто вносить различные изменения и добавлять новые возможности.

В JavaScript создать функцию можно различными способами. Это:

  • Function Declaration;
  • Function Expression;
  • Arrow Function;

Для начала мы рассмотрим способ создания функции с помощью Function Declaration. Function Declaration - это «классический» вариант объявления функции.

Объявление и вызов функции

Операции с функцией в JavaScript можно разделить на 2 шага:

  • объявление (создание) функции;
  • вызов (выполнение) этой функции.

1. Объявление функции. Написание функции посредством Function Declaration начинается с написания ключевого слова function. После этого указывается имя функции, круглые скобки в которых при необходимости перечисляются через запятую параметры и код функции, заключённый в фигурные скобки.

function имя (параметры) {
  // код функции
}

Например:

// объявление функции someName
function someName() {
  alert('Вы вызвали функцию someName!');
}

// function - ключевое слово, которое означает что мы хотим создать функцию
// someName - имя функции
// () - круглые скобки внутри которых при необходимости мы можем поместить параметры через запятую
// { ... } - код или тело функции
JavaScript - Синтаксис объявления функции

При составлении имени функции необходимо руководствоваться теме же правилами, что и при создании имени переменной. Т.е. оно может содержать буквы, цифры (0-9), знаки «$» и «_». В качестве букв рекомендуется использовать только буквы английского алфавита (a-z, A-Z). Имя функции, также как и имя переменной не может начинаться с цифры.

Параметров у функции может быть сколько угодно много или не быть вообще. Круглые скобки в любом случае указываются. Если параметров несколько, то их между собой необходимо разделить посредством запятой. Они позволяют более удобно (по имени) получить переданные аргументы функции при её вызове.

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

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

// выполнение функции, приведённой в предыдущем примере (без передачи ей аргументов)
someName();
JavaScript - Синтаксис вызова функции

Параметры и аргументы функции

Параметры функции - это локальные переменные функции, которые определяются на этапе объявления функции в круглых скобках. Обратиться к параметрам можно только внутри функции, снаружи они не доступны.

Аргументы функции - это значения переданные в функцию при её вызове.

Например:

// объявление функции sayWelcome (userFirstName и userLastName - это параметры)
// userFirstName - будет принимать значения 1 аргумента, а userLastName соответственно значение 2 аргумента
function sayWelcome (userFirstName, userLastName) {
  console.log('Добро пожаловать, ' + userLastName + ' ' + userFirstName);
}

// вызов функции sayWelcome ('Иван' и 'Иванов' - это аргументы)
sayWelcome('Иван', 'Иванов');

// ещё один вызов функции sayWelcome ('Петр', 'Петров' - это аргументы)
sayWelcome('Петр', 'Петров');

Таким образом, параметры – это один из способов в JavaScript, с помощью которого можно получить аргументы функции.

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

Например, вызовем функцию из примера, приведённого выше, без передачи ей одного аргумента:

// вызов функции sayWelcome с одним аргументом 'Петр'
sayWelcome('Петр'); // Добро пожаловать, undefined Петр

Вызов функции sayWelcome без аргументов:

// вызов функции sayWelcome без аргументов
sayWelcome(); // Добро пожаловать, undefined undefined

Специальный объект внутри функции arguments. Получить переданные функции аргументы в JavaScript можно не только с помощью параметров. Это ещё можно выполнить через специальный массивоподобный объект arguments. Он позволяет получить все аргументы, переданные в функцию, а также их количество с помощью свойства length.

function f() {
  // проверим является ли arguments обычным массивом
  console.log(Array.isArray(arguments));
}

f(); // false

Доступ к аргументам через arguments выполняется точно также как к элементам обычного массива, т.е. по их порядковым номерам. Таким образом, argument[0] - позволяет получить первый аргумент, arguments[1] – второй аргумент и т.д.

// объявление функции sum
function sum() {
  const num1 = arguments[0] // получаем значение 1 аргумента
  const num2 = arguments[1] // получаем значение 2 аргумента

  console.log(num1 + num2);
}

sum(7, 4); // 11

Получение аргументов через arguments в основном используется, когда мы заранее не знаем точное их количество.

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

function sum() {
  let sum = 0;
  // arguments.length - число аргументов
  for (let i = 0, length = arguments.length; i < length; i++) {
    if (typeof arguments[i] === 'number') {
      sum += arguments[i];
    }
  }

  console.log(sum);
}

sum(4, 20, 17, -6); // 35
sum('', 3, -5, 32, null); // 30

Через цикл for...of этот пример можно записать так:

function sum() {
  let sum = 0;
  for (argument of arguments) {
    if (typeof argument === 'number') {
      sum += argument;
    }
  }

  console.log(sum);
}

При необходимости мы можем arguments преобразовать в обычный массив. Как это выполнить показано в следующем примере:

function names() {
  // превращаем arguments в полноценный массив
  var argsArr = Array.from(arguments);
  console.log(argsArr);
}

names('Даша', 'Маша', 'Нина'); // ["Даша", "Маша", "Нина"]

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

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

function fa(a, b) {
  const c = 4;
  function fb(d) {
    console.log(a + b + c + d);
  }
  fb(1);
}
fa(3, 5); // 13
fa(4, 7); // 16

// параметр a не доступен за пределами функции fa
console.log(a); // Uncaught ReferenceError: a is not defined

При этом внешняя переменная или функция будет доступна внутри неё.

const a = 10;
function fa(b) {
  console.log(a + b);
}

fa(7); // 17

Передачи одной функции в другую. Колбэки

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

// функция, которая будет выводить в консоль то, что ей передали в виде аргумента
function outputResult(result) {
  console.log(result);
}

// функция, которая принимает на вход 2 аргумента и колбэк
function sum(num1, num2, callback) {
  // вычислим сумму 2 значений и сохраним его в result
  const result = num1 + num2;

  // вызовем колбэк
  callback(result);
}

sum (5, 11, outputResult);

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

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

function myfunc() {};

console.log(typeof myfunc); // function

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

function sum(num1, num2, callback) {
  const result = num1 + num2;

  if (typeof callback === 'function') {
    callback(result);
  }
}

Возвращаемое значение (return)

Оператор return предназначен для возвращения значения выражения в качестве результата выполнения функции. Значение выражения должно быть указано после ключевого слова return.

function f() {
  return выражение;
}

Если оно не указано, то вместо этого значения будет возвращено undefined.

Без использования return:

function sum(a, b) {
  const result = a + b;
}

// вызовем функцию и сохраним её результат в константу result
const result = sum(4, 3);
// выведем результат функции sum(4, 3) в консоль
console.log(result); // undefined

С использованием return:

function sum(a, b) {
  // вернём в качестве результата сумму a + b
  return a + b;
}

// вызовем функцию и сохраним её результат в константу result
const result = sum(4, 3);
// выведем результат функции sum(4, 3) в консоль
console.log(result); // 7

Инструкции, расположенные после return никогда не выполняются:

function sum(a, b) {
  // вернём в качестве результата сумму a + b
  return a + b;
  // код, расположенный после return никогда не выполняется
  console.log('Это сообщение не будет выведено в консоль');
}

sum(4, 90);

Функция, которая возвращает функцию

В качестве результата функции мы можем также возвращать функцию.

Например:

function outer(a) {
  return function(b) {
    return a * b;
  }
}

// в one будет находиться функция, которую возвращает outer(3)
const one = outer(3);
// в two будет находиться функция, которую возвращает outer(4)
const two = outer(4);

// выведем в консоль результат вызова функции one(5)
console.log(one(5)); // 15
// выведем в консоль результат вызова функции two(5)
console.log(two(5)); // 20

Вызовы функции outer(3) и outer(4) возвращают одну и туже функцию, но первая запомнила, что a = 3, а вторая - что a = 4. Это происходит из-за того, что функции в JavaScript «запоминают» окружение, в котором они были созданы. Этот приём довольно часто применяется на практике. Так как с помощью него мы можем, например, на основе одной функции создать другие, которые нужны.

В примере, приведённом выше, мы могли также не создавать дополнительные константы one и two. А вызвать сразу после вызова первой функции вторую.

// выведем в консоль результат вызова функции one(5)
console.log(outer(3)(5)); // 15
// выведем в консоль результат вызова функции two(5)
console.log(outer(4)(5)); // 20

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

Функцию, приведённую в коде мы можем также создать и так:

function outer(a) {
  function inner(b) {
    return a * b;
  }
  return inner;
}

Кроме этого в качестве результата мы можем также возвратить внешнюю функцию:

function fa() {
  return 'Привет!';
}

function fb() {
  return fa;
}

fb()(); // Привет!

Рекурсия

Функцию можно также вызвать внутри самой себя. Это действие в программировании называется рекурсией.

Кроме этого необходимо предусмотреть условия для выхода из рекурсии. Если это не сделать функция будет вызывать сама себя до тех пор, пока не будет брошена ошибка, связанная с переполнением стека.

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

function fact(n) {
  // условие выхода из рекурсии
  if (n === 1) {
    return 1;
  }

  // возвращаем вызов функции fact(n - 1) умноженное на n
  return fact(n - 1) * n;
}
console.log(fact(5)); // 120

Пример, в котором используя рекурсию выведем числа от указанного до 10:

function counter(value) {
  // условие выхода из рекурсии
  if (value < 10) {
    console.log(value);

    // возвращаем вызов функции counter(value + 1)
    return counter(value + 1);
  }
}

counter(1); // 1, 2, 3, 4, 5, 6, 7, 8, 9
counter(7); // 7, 8, 9

Перегрузка функций в JavaScript

Перегрузка функций в программировании – это возможность объявлять в одном месте несколько функций с одинаковыми именами. Отличаются такие функции друг от друга параметрами. Используется перегрузка функций для того, чтобы можно было вызвать подходящую под переданные аргументы функцию.

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

Например, того чтобы проверить имеет параметр значение или нет, мы можем проверить его значения на undefined. Узнать количества переданных аргументов функции можно через arguments.length. Определить значения параметра можно используя typeof или instanceof.

Например, создадим функцию bodyBgColor, которая будет иметь 2 режима работы. Если её вызвать без аргументов, то она будет возвращать цвет фона body. А если с текстовым аргументом, то она будет устанавливать цвет фона body.

// объявление функции bodyBgColor
function bodyBgColor(color) {
  // если параметр color имеет в качестве значения строку, то установим цвет фона body
  if (typeof color === 'string') {
    document.body.style.backgroundColor = color;
  }

  // вернём в качестве результата текущий цвет фона body
  return getComputedStyle(document.body).backgroundColor;
}

// получим текущий цвет body и выведем его в консоль
console.log(bodyBgColor());

// установим новый цвет фона body
bodyBgColor('green');

Пример реализации «перегруженной» функции для вычисления оптимального количества ккал, которых необходимо человеку в день:

function calculateСalories(gender, height) {
  let result = gender === 'man' ? (height - 100) * 20 : (height - 105) * 19;
  if (typeof arguments[2] === 'number') {
    result *= arguments[2];
  }
  return result.toFixed(0);
}

console.log(`Оптимальное кол-во ккал: ${calculateСalories('man', 185)}`);
console.log(`Оптимальное кол-во ккал: ${calculateСalories('woman', 168, 1.2)}`);
console.log(`Оптимальное кол-во ккал: ${calculateСalories('woman', 168)}`);

Новые возможности, которые появились в ES6+ для функций

Значение параметра по умолчанию

В языке, начиная с версии ECMAScript 6+ (2015+) параметру функции можно задать значение по умолчанию.

Например, установим параметру color значение по умолчанию '#009688':

function bodyBgColor(color = '#009688') {
  document.body.style.backgroundColor = color;
}

// при вызове функции без указания аргументов цвет фона body будет установлен, равным '#009688'
setBGColor();
// при указании аргумента цвет фона body будет установлен в соответствии с его значением
setBGColor('red'); // цвет фона будет равен red

До появление такой возможности в языке, задание параметру значения по умолчанию выполнялось так:

function setBGColor(color) {
  // устанавливаем color значение по умолчанию '#009688', если он имеет тип undefined
  color = typeof color === 'undefined' ? '#009688' : color;
  // устанавливаем цвет фона body равным значению color
  document.body.style.backgroundColor = color;
}

Оставшиеся параметры (rest parameters)

Если при вызове функции ей передать аргументов больше, чем у нас есть параметров, то получить оставшиеся значения можно с помощью, так называемых rest patameters.

// ...nums - оставшиеся параметры, к которым можно обратиться в данном случае по nums
function calculate(action, ...nums) {
  let result = 0;
  nums.forEach(function(num) {
    switch (action) {
      case 'sum':
        result += num;
        break;
      case 'multiply':
        result *= num;
        break;
    }
  });

  return result;
}

console.log(calculate('sum', 3, 4, 21, -4)); // 24
console.log(calculate('multiply', 1, 4, 3)); // 12

Что такое встроенные (стандартные) функции?

В JavaScript имеется огромный набор встроенных (стандартных) функций. Данные функции уже описаны в самом движке браузера. Практически все они являются методами того или иного объекта.

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

// вызов функции alert
alert("Некоторый текст");
JavaScript - Вызов функции alert

Функция в JavaScript в результате своего выполнения всегда возвращает результат, даже если он явно не определён с помощью оператора return. Этот результат значение undefined.

// 1. функция, не возвращающая никакого результата
function sayWelcome (userFirstName, userLastName) {
  console.log("Добро пожаловать, " + userLastName + " " + userFirstName);
}
// попробуем получить результат у функции, которая ничего не возвращает
console.log(sayWelcome ("Иван", "Иванов"));
// 2. функция, содержащая оператор return без значения
function sayDay (day) {
  day = "Сегодня, " + day;
  return;
  //эта инструкция не выполнится, т.к. она идёт после оператора return
  console.log(day);
}
// попробуем получить результат у функции, которая содержит оператор return без значения
console.log(sayDay("21 февраля 2016г."));
JavaScript - Получить значение у функции, которая ничего не возвращает

Такой же результат будет получен, если для оператора return не указать возвращаемое значение.