Функции обратного вызова
1. Введение
В JavaScript функции не отличаются от чисел, строк или массивов - это просто специальный тип данных (объект), который можно хранить в переменной или передавать как аргумент в другую функцию.
Функция высшего порядка — функция, принимающая в качестве параметров другие функции или возвращающая функцию как результат.
Функция обратного вызова (callback) — это функция, которая передается другой функции в качестве аргумента и та, в свою очередь, вызывает переданную функцию.
const printMessage = function (message) {
console.log(message);
};
const higherOrderFunction = function (callback) {
const string = 'HOCs are awesome';
callback(string);
};
higherOrderFunction(printMessage);
Copy
Функции обратного вызова применяются для обработки действий пользователя на странице, при вызове функций к определенному времени, при обработке запросов на сервер и др.
2. Абстрагирование повторения
Абстракция — скрытие деталей реализации. Позволяет думать о задачах на более высоком (абстрактном) уровне.
Функции - это хороший способ построения абстракций. Допустим, скрипт выполняет какое-то действие определенное количество раз. Для этого можно написать цикл for
.
for (let i = 0; i < 10; i += 1) {
console.log(i);
}
Copy
Можем ли мы абстрагировать «делать что-то N раз» как функцию? - да, напишем функцию, которая вызывает console.log()
N раз.
const repeatLog = function (n) {
for (let i = 0; i < n; i += 1) {
console.log(i);
}
};
repeatLog(5);
Copy
Но что, если мы хотим сделать что-то, кроме логирования чисел? Поскольку «делать что-то» можно представить как функцию, а функции - это просто значения, мы можем передать действие как аргумент.
const printValue = function (value) {
console.log(value);
};
const prettyPrint = function (value) {
console.log('Logging value: ', value);
};
const repeat = function (n, action) {
for (let i = 0; i < n; i += 1) {
action(i);
}
};
// Передаем printValue как callback-функцию
repeat(3, printValue);
// 0
// 1
// 2
// Передаем prettyPrint как callback-функцию
repeat(3, prettyPrint);
// Logging value: 0
// Logging value: 1
// Logging value: 2
Copy
Часто callback-функции анонимны и объявляются как стрелочные функции прямо во время передачи.
const repeat = function (n, action) {
for (let i = 0; i < n; i += 1) {
action(i);
}
};
const labels = [];
repeat(5, value => {
labels.push(`Label ${value + 1}`);
});
console.log(labels); // ["Label 1", "Label 2", "Label 3", "Label 4", "Label 5"]
Copy
3. Фильтрация массива
Напишем функцию фильтрации элементов массива. Первый параметр array
- это массив, будем перебирать его используя цикл for...of
.
const filter = function (array) {
for (const element of array) {
}
};
Copy
Второй параметр test
- это callback-функция, которую будет необходимо выполнить для каждого элемента массива.
const filter = function (array, test) {
for (const element of array) {
test(element);
}
};
Copy
Функция filter
создает новый массив, в который будет добавляться результат выполнения callback-функции test
над каждым элементом массива array
. Результатом работы функции будет массив отфильтрованных элементов.
const filter = function (array, test) {
const filteredElements = [];
for (const element of array) {
test(element);
}
return filteredElements;
};
Copy
Если элемент массива проходит тест, то есть callback-функция возвращает true
, он добавляться в отфильтрованный массив.
const filter = function (array, test) {
const filteredElements = [];
for (const element of array) {
const passed = test(element);
if (passed) {
filteredElements.push(element);
}
}
return filteredElements;
};
Copy
При таком подходе мы можем выполнять фильтрацию массива по критерию используя всего одну функцию для перебора, а операции над каждым элементом будут зависеть от callback-функции.
const filter = function (array, test) {
const filteredElements = [];
for (const element of array) {
const passed = test(element);
if (passed) {
filteredElements.push(element);
}
}
return filteredElements;
};
const fruits = [
{ name: 'apples', quantity: 200, isFresh: true },
{ name: 'grapes', quantity: 150, isFresh: false },
{ name: 'bananas', quantity: 100, isFresh: true },
];
const freshFruits = filter(fruits, fruit => fruit.isFresh);
console.log(freshFruits); // массив с объектами apples и bananas
const fruitsWithQuantity = filter(fruits, fruit => fruit.quantity >= 120);
console.log(fruitsWithAmount); // массив с объектами apples и grapes
Last updated