Возврат функции из функции в JavaScript

Функция может вернуть не только строку, число или объект. Она может вернуть другую функцию.

function createMessage() {
  return function () {
    console.log('Привет!');
  };
}

let message = createMessage();

message();

Результат:

Привет!

Функция createMessage() вернула новую функцию. Мы записали ее в переменную message, а потом вызвали.

Что значит вернуть функцию

Оператор return возвращает результат работы функции.

Обычно это какое-то значение:

function getName() {
  return 'Анна';
}

let name = getName();

Но так как функция в JavaScript тоже является значением, ее тоже можно вернуть через return.

function getAction() {
  return function () {
    console.log('Действие выполнено');
  };
}

В этом примере результатом вызова getAction() будет функция.

Простой пример

Сделаем функцию, которая создает другую функцию.

function createHello() {
  function sayHello() {
    console.log('Здравствуйте!');
  }

  return sayHello;
}

let hello = createHello();

hello();

Результат:

Здравствуйте!

Обратите внимание: внутри return мы пишем sayHello без скобок.

return sayHello;

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

Вызов возвращенной функции

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

function createLogger() {
  return function () {
    console.log('Лог записан');
  };
}

let logger = createLogger();

logger();

Иногда такую функцию вызывают сразу.

function createLogger() {
  return function () {
    console.log('Лог записан');
  };
}

createLogger()();

Здесь первая пара скобок вызывает createLogger(), а вторая пара скобок вызывает функцию, которую она вернула.

Функция с настройками

Часто внешняя функция принимает настройки, а внутренняя функция использует их позже.

function createGreeting(greeting) {
  return function (name) {
    console.log(greeting + ', ' + name + '!');
  };
}

let sayHello = createGreeting('Привет');
let sayGoodMorning = createGreeting('Доброе утро');

sayHello('Анна');
sayGoodMorning('Игорь');

Результат:

Привет, Анна!
Доброе утро, Игорь!

Функция createGreeting() создала две разные функции. Первая запомнила приветствие ‘Привет’, вторая - ‘Доброе утро’.

Возврат разных функций

Функция может вернуть одну из нескольких функций в зависимости от условия.

function getOperation(type) {
  if (type === 'sum') {
    return function (a, b) {
      return a + b;
    };
  }

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

let operation = getOperation('sum');

console.log(operation(2, 3));

Результат:

5

Мы выбрали нужную функцию по строке ‘sum’, сохранили ее в переменную operation и вызвали.

Связь с замыканием

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

function createCounter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}

let counter = createCounter();

console.log(counter());
console.log(counter());
console.log(counter());

Результат:

1
2
3

Функция counter продолжает помнить переменную count, хотя createCounter() уже выполнилась. Это и есть замыкание.

Зачем это нужно

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

function createMultiplier(multiplier) {
  return function (number) {
    return number * multiplier;
  };
}

let double = createMultiplier(2);
let triple = createMultiplier(3);

console.log(double(5));
console.log(triple(5));

Результат:

10
15

Функция createMultiplier() создает новые функции с разным поведением. double() умножает на 2, а triple() - на 3.

Итого

1. Функция может вернуть другую функцию через return.

2. Чтобы вернуть саму функцию, ее имя пишут без скобок.

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

4. Запись createFunction()() означает: сначала вызвать внешнюю функцию, потом вызвать функцию, которую она вернула.

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