Перейти к содержимому
Теория · Методы массивов · урок 1 из 12

Функция как аргумент: forEach

Чему вы научитесь

Чему вы научитесь:

  • передавать функцию в метод массива и отличать её от вызова функции;
  • получать из массива новый массив через map и filter, а одно значение — через reduce;
  • искать элемент через find и проверять условие через some и every;
  • сортировать числа функцией сравнения, не теряя исходный порядок.
Конвейер forEach подаёт ящики 3 5 8 по одному работнику с бейджем show

Представьте конвейер на фабрике. По ленте один за другим едут ящики, а у ленты стоит работник. Ящик подъезжает к нему, работник делает с ним своё дело, и лента подаёт следующий. Работнику не нужно ходить по складу и считать ящики: подачу берёт на себя конвейер.

Массив и его методы устроены так же:

  • массив — это лента с элементами;
  • метод массива — конвейер, который сам подаёт элементы по одному;
  • работника приносите вы: это функция, которую метод вызывает для каждого элемента.

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

JavaScript
const nums = [3, 5, 8];

function show(n) {
    console.log(n);
}

nums.forEach(show);
// 3
// 5
// 8

Давайте разберём пример по строкам:

  1. const nums = [3, 5, 8]; — массив из трёх чисел, наша лента.
  2. function show(n) описывает работника: он получает одно число и печатает его.
  3. nums.forEach(show) ставит работника к ленте. Метод вызывает show три раза: с 3, с 5 и с 8.

Счётчик, условие и индексы остаются внутри метода, и ошибиться в границах цикла негде.

Функция — тоже значение

Имя функции без скобок — это сама функция, такое же значение, как число или строка. Её можно сохранить в константе и передать в другую функцию аргументом. Скобки после имени означают вызов: show(3) выполняет тело функции прямо сейчас.

На конвейере разница видна сразу:

  • show — сам работник, его можно поставить к ленте;
  • show(3) — работник уже обработал число 3, и у вас в руках только результат его работы.

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

Что такое колбэк, часто спрашивают на собеседовании. Ответ укладывается в одну фразу: это функция, которую передали аргументом, чтобы её вызвал кто-то другой.

Колбэк прямо в вызове

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

JavaScript
const words = ["red", "green"];

words.forEach((word, i) => {
    console.log(i, word);
});
// 0 red
// 1 green

При каждом вызове forEach передаёт колбэку три аргумента:

  1. сам элемент, здесь word;
  2. его индекс, здесь i;
  3. весь массив, который обычно не нужен.

Поэтому программа печатает 0 red, а затем 1 green. Если индекс не нужен, колбэку хватит одного параметра: лишние аргументы функция не замечает.

Колбэк вызывается по порядку, от первого элемента к последнему. Следующая строка программы выполняется только после последнего вызова.

Что возвращает forEach

forEach ничего не собирает. Он вызывает колбэк ради действия, например печати, и всегда возвращает undefined. Значение, которое вернул колбэк, пропадает:

JavaScript
const result = [1, 2, 3].forEach((n) => n * 2);

console.log(result); // undefined

Колбэк здесь возвращает 2, 4 и 6, но конвейер эти числа никуда не кладёт. Работник ставит на каждый ящик штамп, а коробки для готовых вещей у ленты нет.

Колбэк может менять переменную снаружи. Вызов nums.forEach((n) => { total += n; }) прибавляет каждый элемент к переменной total, объявленной через let до вызова. Так результат всё же получается, но собирать его приходится вручную.

forEach не остановить

Здесь аналогия с конвейером перестаёт работать. Настоящий работник может нажать кнопку и остановить ленту, а у forEach такой кнопки нет.

Прервать forEach на середине нельзя: break и continue внутри колбэка дают SyntaxError, и метод всегда доходит до конца массива. Когда обход нужно остановить, пишут for…of.

Частая ошибка

Функцию передали со скобками:

JavaScript
function show(n) {
    console.log(n);
}

[1, 2].forEach(show()); // ✗
TEXT
TypeError: undefined is not a function

Скобки вызывают show сразу, ещё до forEach, и без аргумента, поэтому программа сначала печатает undefined. Этот вызов возвращает undefined, и forEach получает вместо функции именно это значение. Передайте имя без скобок: [1, 2].forEach(show).

Главное

  • forEach сам обходит массив и вызывает переданную функцию для каждого элемента.
  • Имя функции без скобок — сама функция, а скобки её вызывают; в метод передают имя без скобок.
  • Колбэк — функция, переданная аргументом; функция высшего порядка принимает такую функцию.
  • forEach всегда возвращает undefined и доходит до конца массива.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом