Перейти к основному содержимому

Замыкания +

  • Это своего рода взаимодействие параметров родительской функции с параметрами своей возвращаемой вложенной функции.
  • Так как вложенная функция "видит" все параметры своей родительской функции, то эта вложенная функция может с ними взаимодействовать и сочетать со cвоими собственными параметрами.
  • Это происходит из-за цепочек областей видимости
function someParentFunc(a) {
return function someChildrenFunc(b) {
// a - род. параметр, b - локальный
console.log(a + b);
};
}

ЗАПИСЬ 1 - двойной вызов

Особого смысла нет, так как не даёт гибкости.

someParentFunc(1)(2); // 3

ЗАПИСЬ 2

  • Используется на практике
  • Сохраняем в переменную вызвов родительской функции с каким-либо параметром.
  • Так как род. функция возвращает дочернюю функцию, то сохранённая переменная будет хранить вложенную функцию, которую можно вызывать уже с требуемыми нами параметрами любое кол-во раз.
const a = someParentFunc(1);

// потом вызываем вложенную функцию с параметром 2
a(2); // 3

И этот сохраненный вызов можно так же вызывать с разными параметрами.

a(3); // 4
a(14); // 15
  • Замыкания дают определенную гибкость, можно комбинировать вызовы с различными параметрами, хотя можно сделать все и через простую функцию с двумя параметрами
  • Гибкость заключается в том, что можно сохранить вызов родительской функции с определенным параметром, а далее вызывать через сохранение вложеннную функцию с различными параметрами.
  • Можно использовать при случаях, когда один параметр в обычной функции редко изменяется, а другой часто
// меньше гибкости
function(a, b) { ... }

// VS

// больше гибкости
function(a) {
return function(b) { ... }
}

Примеры замыканий

function makeCounter(start = 0) {
let count = start;

// эта вложенная функция видит count сверху
return () => ++count;
}

const counter = makeCounter(10);

counter(); // 11
counter(); // 12
counter(); // 13

Множитель (одно число «запоминается»)

Внешняя функция фиксирует множитель, внутренняя принимает только второе число.

function multiplyBy(factor) {
return function (n) {
return n * factor;
};
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

double(5); // 10
triple(5); // 15

Префикс для сообщений

Замыкание хранит строку prefix, каждый вызов log её «помнит».

function createLogger(prefix) {
return function (message) {
console.log(`${prefix}: ${message}`);
};
}

const appLog = createLogger('[APP]');
const dbLog = createLogger('[DB]');

appLog('старт'); // [APP]: старт
dbLog('подключено'); // [DB]: подключено

Базовый URL для запросов

Один раз передаём корень API, дальше добавляем только путь.

function createApiClient(baseUrl) {
return function (path) {
return fetch(baseUrl + path);
};
}

const api = createApiClient('https://api.example.com');
// api('/users') → запрос к https://api.example.com/users

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