Клавиша / esc

.forEach()

Сколькими способами можно обойти массив? Это ещё один способ, но без явного описания цикла.

Время чтения: меньше 5 мин

Кратко

Скопировано

Метод массива forEach() позволяет применить колбэк-функцию ко всем элементам массива. Можно использовать вместо классического цикла for. В отличие от него forEach() выглядит более читабельным и понятным.

Пример

Скопировано
        
          
          const numbers = [1, 2, 3, 4]numbers.forEach((num) => {  const square = num * num  console.log('Квадрат числа равен: ' + square)})
          const numbers = [1, 2, 3, 4]

numbers.forEach((num) => {
  const square = num * num
  console.log('Квадрат числа равен: ' + square)
})

        
        
          
        
      

Выведет:

Квадрат числа равен: 1
Квадрат числа равен: 4
Квадрат числа равен: 9
Квадрат числа равен: 16

Интерактивный пример:

Открыть демо в новой вкладке

Совсем любопытные могут заглянуть в исходники, чтобы посмотреть как forEach() активно используется в коде этого примера.

Как пишется

Скопировано

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

        
          
          function sliceFruit(fruit) {  console.log('Разрезаю ' + fruit + '!')}const fruits = ['🍎', '🍊', '🍋', '🍓', '🥝']fruits.forEach(sliceFruit)
          function sliceFruit(fruit) {
  console.log('Разрезаю ' + fruit + '!')
}

const fruits = ['🍎', '🍊', '🍋', '🍓', '🥝']

fruits.forEach(sliceFruit)

        
        
          
        
      

Или создать её прямо в месте вызова:

        
          
          const food = ['🍔', '🍟', '🍦']food.forEach((item) => {  console.log('Мам, купи ' + item + '!')})
          const food = ['🍔', '🍟', '🍦']

food.forEach((item) => {
  console.log('Мам, купи ' + item + '!')
})

        
        
          
        
      

Важно знать, какие параметры принимает колбэк. Всего их три:

  • item — элемент массива в текущей итерации;
  • index — индекс текущего элемента;
  • arr — сам массив, который мы перебираем.

Вернёмся к примеру с едой:

        
          
          const food = ['🍔', '🍟', '🍦']food.forEach((item, index, arr) => {  console.log('Текущий элемент ' + item)  console.log('Его индекс ' + index)  console.log('Исходный массив ' + arr)})
          const food = ['🍔', '🍟', '🍦']

food.forEach((item, index, arr) => {
  console.log('Текущий элемент ' + item)
  console.log('Его индекс ' + index)
  console.log('Исходный массив ' + arr)
})

        
        
          
        
      

Выведет:

Текущий элемент 🍔
Его индекс 0
Исходный массив ['🍔', '🍟', '🍦']
Текущий элемент 🍟
Его индекс 1
Исходный массив ['🍔', '🍟', '🍦']
Текущий элемент 🍦
Его индекс 2
Исходный массив ['🍔', '🍟', '🍦']

Поскольку forEach отдаёт колбэку три параметра, если не указать иного, то можно просто передать (а не вызвать) колбэк без указания параметров, чтобы forEach отдал все три параметра и колбэк принял и обработал их все.

Этот простой код…

        
          
          food.forEach(  console.log)
          food.forEach(
  console.log
)

        
        
          
        
      

…выведет и значение элемента, и его индекс, и весь массив:

🍔 0 (3) ['🍔', '🍟', '🍦']
🍟 1 (3) ['🍔', '🍟', '🍦']
🍦 2 (3) ['🍔', '🍟', '🍦']

Как понять

Скопировано

Метод forEach() можно использовать, когда вам необходимо совершить одну и ту же операцию над всеми элементами массива.

Хотя в JavaScript уже есть возможность делать это, используя цикл for, метод forEach() — это отличная альтернатива с рядом преимуществ:

  • Использование метода forEach() является декларативным способом обозначить нашу операцию. С точки зрения читабельности кода это больше приближено к естественному языку и лаконично.
  • Позволяет удобно получать элемент в текущей итерации, без необходимости всякий раз обращаться к массиву по индексу.

Однако вместе с тем мы получаем и несколько недостатков:

  • В forEach() не будут работать return, break и continue, а следовательно, мы никак не можем прервать или пропустить итерацию. Потому, если для решения задачи необходимо воспользоваться каким-либо из этих операторов, придётся использовать обычный цикл for.
  • forEach() обрабатывает элементы массива в прямом порядке, то есть мы не можем пройти по массиву с конца.

💡 Метод forEach() автоматически встроен в любой массив.

Сработает:

        
          
          const empty = []const someNums = [1, 2, 3]console.log(empty.forEach)// Выведет функциюconsole.log(someNums.forEach)// И здесь тожеconst obj = {}console.log(obj.forEach)// undefined, потому что у объектов нет такого метода
          const empty = []
const someNums = [1, 2, 3]

console.log(empty.forEach)
// Выведет функцию
console.log(someNums.forEach)
// И здесь тоже

const obj = {}
console.log(obj.forEach)
// undefined, потому что у объектов нет такого метода

        
        
          
        
      

На практике

Скопировано

Егор Огарков советует

Скопировано

🛠 Имена аргументов в функции-колбэке можно давать любые, главное, чтобы код было удобно читать.

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

        
          
          const nums = [1, 2, 3, 4, 5]nums.forEach((num, index, arr) => {  // Добавим к первому числу 9  if (index === 0) {    num = num + 9  }  // А последнее умножим на 2  else if (index === arr.length - 1) {    num = num * 2  }  console.log(num)})
          const nums = [1, 2, 3, 4, 5]

nums.forEach((num, index, arr) => {
  // Добавим к первому числу 9
  if (index === 0) {
    num = num + 9
  }
  // А последнее умножим на 2
  else if (index === arr.length - 1) {
    num = num * 2
  }
  console.log(num)
})

        
        
          
        
      

Выведет:

10
2
3
4
10

На собеседовании

Скопировано
Задать вопрос в рубрику
🤚 Я знаю ответ

Скопировано

Методы forEach() и map() определены на нескольких структурах данных. Мы рассмотрим чем отличаются эти методы для массивов.

Оба метода принимают колбэк, который вызывается для каждого элемента. Разница в том, что метод forEach() ничего не возвращает, а метод map() возвращает новый массив с результатами вызова колбэка на каждом исходном элементе. Если переданный колбэк ничего не возвращает в новом массиве появится undefined

Вы можете вернуть значение и из колбэка для forEach() но оно никак не будет использоваться дальше.

        
          
          [1,2,3].forEach(a => a + 3);
          [1,2,3].forEach(a => a + 3);

        
        
          
        
      

Используя map() вы можете создавать цепочки вызовов. Если же вы будете использовать forEach() так сделать не получится.

        
          
          const myArray = [4, 2, 8, 7, 3, 1, 0];const myArray2 = myArray.map(item => item * 2).sort((a, b) => a - b);console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]
          const myArray = [4, 2, 8, 7, 3, 1, 0];
const myArray2 = myArray.map(item => item * 2).sort((a, b) => a - b);

console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]
console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]

        
        
          
        
      

В примере выше изменился только myArray2.

Для закрепления, реализуем ту же самую логику при помощи forEach().

        
          
          const myArray = [4, 2, 8, 7, 3, 1, 0];let myArray2 = [];myArray.forEach(item => {  myArray2.push(item * 2);});myArray2 = myArray2.sort((a, b) => a - b);console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]
          const myArray = [4, 2, 8, 7, 3, 1, 0];
let myArray2 = [];

myArray.forEach(item => {
  myArray2.push(item * 2);
});

myArray2 = myArray2.sort((a, b) => a - b);

console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]
console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]